我目前正在进行一个个人学习项目,在 XML 数据库中进行阅读。我发现自己正在编写收集数据的函数,但我不确定返回它们的快速方法是什么。
哪个通常更快:
yield
s,或append()
,然后是
return
接下来的
list
?
yield
会比
append()
更快,反之亦然。
yield
具有“懒惰”的巨大优势,而速度通常不是使用它的“最佳”原因。但如果它在您的环境中有效,那么就没有理由不使用它:
# yield_vs_append.py
data = range(1000)
def yielding():
def yielder():
for d in data:
yield d
return list(yielder())
def appending():
lst = []
for d in data:
lst.append(d)
return lst
这是结果:
python2.7 -m timeit -s "from yield_vs_append import yielding,appending" "yielding()"
10000 loops, best of 3: 80.1 usec per loop
python2.7 -m timeit -s "from yield_vs_append import yielding,appending" "appending()"
10000 loops, best of 3: 130 usec per loop
至少在这个非常简单的测试中,
yield
我最近问了自己一个类似的问题,探索通过附加到列表或通过生成器来生成列表(或元组)的所有排列的方法,并发现(对于长度为 9 的排列,需要大约一秒钟左右的时间才能生成):
itertools.permutations
时间的三倍
yield
)可以减少大约。 20%
itertools.permutations
时间的两倍。
if __name__ == '__main__':
import cProfile
cProfile.run("main()")
TH4Ck 的yieling() 有一个更快的替代方案。这是列表理解。
In [245]: def list_comp():
.....: return [d for d in data]
.....:
In [246]: timeit yielding()
10000 loops, best of 3: 89 us per loop
In [247]: timeit list_comp()
10000 loops, best of 3: 63.4 us per loop
首先你必须决定,如果你需要生成器,这也得到了改进的方法。就像列表生成器“[elem for elem in somethink]”。如果您只使用列表中的值进行某些操作,建议使用生成器。但是,如果您需要列表进行许多更改,并同时处理许多元素,则必须是列表。 (就像标准程序员使用列表的 70% 次一样,生成器会更好。使用更少的内存,只是很多人看不到列表的其他方式。不幸的是,在我们这个时代,许多人对良好的优化嗤之以鼻,而只是为了工作.)
如果你使用列表生成器来提高回报,那么让我们对收益人员做同样的事情。不管怎样,我们为 Python 编程语言中的所有操作提供了多种更优化的方法。
data = range(1000)
def yielder():
yield from data
def appending():
L = []
app = list.append
for i in data:
app(L, i)
return L
def list_gen():
return [i for i in data]
当然,追加会比其他想法慢,因为我们创建并扩展列表任何循环时间。只是循环“for”是非常不优化的,如果你可以避免这个,那就这样做。因为在任何步骤中,该函数都会加载下一个元素并写入我们的变量,以在内存中获取该对象值。所以我们跳转到任何元素,创建引用,在循环中扩展列表(声明的方法是巨大的速度优化器),当我们生成返回时,摘要在两个列表中得到了 2000 个元素。
list_gen 不太节省内存,我们只返回元素,但像 up 一样,我们生成第二个列表。现在我们得到了两个列表,原始数据和她的副本。总结2000个要素。只是我们避免了创建变量引用的步骤。因为我们的列表中的生成避免了这一步。只需写元素即可。
yielder 使用的内存最少,因为我们刚刚从数据中获得了值。我们避免提及任何一项。例如:
data = range(1000)
def yielder():
yield from data
def list_gen():
return [i for i in data]
#Now we generate next reference after line [i for i in data]
for i in list_gen():
#some instruction
#This is our first reference, becouse was yield from data.
for i in yielder():
#some instruction
某些指令仅使用一个元素,而不是全部来自列表,下一个值生成器将在下一个循环中返回,而不是杂志所有 1000 个元素写入引用。
抱歉,这个话题有点挖掘,就在我不小心从谷歌搜索中交叉出来的时候,其他初学者Python程序员都可以看到这个废话。
关于
yield
的快速说明,它不是持久的。缺乏持久性会让新开发人员感到困惑 -
def count_to_five():
for i in range(5):
yield i + 1
five_count = count_to_five()
print(list(five_count)) # [1, 2, 3, 4, 5]
# What? I didn't do anything. I just printed the result again!
print(list(five_count)) # []
我意识到这不是您好奇的“速度”,但开发速度是使用列表或生成器时要考虑的一个指标。这也不是一个病态的例子;有人可能使用打印语句来调试结果,但没有意识到他们这样做正在改变结果。