您始终可以编写自己的do_all
函数:
def do_all(iterable, func):
for i in iter(iterable):
func(i)
然后随时调用它。
使用显式for
循环确实没有性能问题。
使用列表推导或 存在性能问题,但map
仅在构建结果列表时。显然,如果您必须在此过程中构建一个 500M 的列表,那么迭代超过 500M 的项目会慢很多。
值得在这里指出的是,对于像绘制精灵列表这样的事情,几乎可以肯定不会出现这种情况。您没有 500M 的精灵要绘制。如果你这样做了,它可能会比创建一个包含 5 亿份无副本的列表要长得多。在大多数可能的情况下,您确实需要对 500M 个对象做同样非常简单的事情,有更好的解决方案,比如切换到numpy
. 但是有一些可以想象的情况可能会出现这种情况。
解决这个问题的简单方法是使用生成器表达式或itertools.imap
(或者,在 Python 3 中,只是map
),然后通过编写dispose
函数来处理这些值。一种可能:
def dispose(iterator):
for i in iterator:
pass
然后:
dispose(itertools.imap(Sprite.draw, sprite_list))
你甚至可以定义do_all
为:
def do_all(iterable, func):
dispose(itertools.imap(func, iterable))
如果你这样做是为了清楚或简单,我认为这是错误的。for 循环版本非常容易阅读,而且这个版本看起来就像您正在尝试使用错误的函数名称和语法编写 Haskell。
如果你是为了性能而这样做......好吧,如果现实生活中的性能情况很重要(这似乎不太可能),你可能想要玩一堆不同的潜在实现dispose
,并可能将其移dispose
回do_all
以避免额外的函数调用,甚至可能在 C 中实现整个事情(借用 stdlib 的 itertools.c 中的快速迭代代码)。
或者,更好的是pip install more-itertools
,然后使用more_itertools.consume
. 对于它的价值,当前版本只是这样做collections.deque(iterator, maxlen=0)
,并且在针对自定义 C 实现的测试中,它的速度不到 1%(除了非常小的迭代器——我的系统上的截止值是 19),所以它可能不值得在C. 但是如果有人这样做,或者如果某些未来的 Python(或 PyPy)提供了一种更快的方法来实现它,那么它很可能会more-itertools
在你发现它并更改你的代码之前被添加进去。