gpt4 book ai didi

python - 总和有什么作用?

转载 作者:太空狗 更新时间:2023-10-30 01:25:32 26 4
gpt4 key购买 nike

起初,我想测试生成器和列表理解之间的内存使用情况。这本书给了我一个小的工作台代码片段,我在我的 PC(python3.6,Windows)上运行它,发现了一些意想不到的东西。

  1. 书上说,因为列表推导式必须创建一个真实的列表并为其分配内存,所以从列表推导式迭代必须比从生成器迭代慢。
  2. 当然,列表理解比生成器使用更多的内存。

以下是我的代码,不符合之前的意见(在 sum 函数内)。

import tracemalloc
from time import time


def timeIt(func):
start = time()
func()
print('%s use time' % func.__name__, time() - start)
return func


tracemalloc.start()

numbers = range(1, 1000000)


@timeIt
def lStyle():
return sum([i for i in numbers if i % 3 == 0])


@timeIt
def gStyle():
return sum((i for i in numbers if i % 3 == 0))


lStyle()

gStyle()

shouldSize = [i for i in numbers if i % 3 == 0]

snapshotL = tracemalloc.take_snapshot()
top_stats = snapshotL.statistics('lineno')
print("[ Top 10 ]")
for stat in top_stats[:10]:
print(stat)

输出:

lStyle use time 0.4460000991821289
gStyle use time 0.6190001964569092
[ Top 10 ]
F:/py3proj/play.py:31: size=11.5 MiB, count=333250, average=36 B
F:/py3proj/play.py:33: size=448 B, count=1, average=448 B
F:/py3proj/play.py:22: size=136 B, count=1, average=136 B
F:/py3proj/play.py:17: size=136 B, count=1, average=136 B
F:/py3proj/play.py:14: size=76 B, count=2, average=38 B
F:/py3proj/play.py:8: size=34 B, count=1, average=34 B

两点:

  • 生成器使用更多时间和相同内存空间。
  • sum 函数中的列表理解似乎无法创建总列表

我想也许 sum 函数做了一些我不知道的事情。谁能解释一下?

这本书是 High Perfoamance Python.chapter 5。但是我自己做了一些与书中不同的事情来检查其他上下文中的有效性。他的代码在这里 book_code ,他没有把 list-comprehension 放在 sum 函数中。

最佳答案

当涉及到时间性能测试时,我确实依赖 timeit 模块,因为它会自动执行代码的多次运行。

在我的系统上,timeit 给出了以下结果(由于多次运行,我大大减小了大小):

>>> timeit.timeit("sum([i for i in numbers if i % 3 == 0])", "numbers = range(1, 1000)")
59.54427594248068
>>> timeit.timeit("sum((i for i in numbers if i % 3 == 0))", "numbers = range(1, 1000)")
64.36398425334801

所以生成器慢了大约 8% (*)。这并不是一个真正的惊喜,因为生成器必须即时执行一些代码来获取下一个值,而预先计算的列表只会增加其当前指针。

内存评估恕我直言更复杂,所以我使用了 Compute Memory footprint of an object and its contents (Python recipe)来自激活状态

>>> numbers = range(1, 100)
>>> numbers = range(1, 100000)
>>> l = [i for i in numbers if i % 3 == 0]
>>> g = (i for i in numbers if i % 3 == 0)
>>> total_size(l)
1218708
>>> total_size(g)
88
>>> total_size(numbers)
48

我的解释是,列表的所有项目都使用内存(这不足为奇),而生成器只需要很少的值和一些代码,因此生成器的内存占用要小得多。

我强烈认为您将 tracemalloc 用于某些不适合的用途。它旨在搜索可能的内存泄漏(大块内存从未被释放),而不是控制单个对象使用的内存。


注意:我只能测试小尺寸。但是对于非常大的尺寸,列表可能会耗尽可用内存并且机器将使用来自交换的虚拟内存。在那种情况下,列表版本会变得很慢。更多详情 there

关于python - 总和有什么作用?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50637863/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com