Tyl*_*ton 23 python python-itertools python-3.x
我可以想到的Python itertools.repeat()类的每一个用途,我可以想到另一个同样(可能更多)可接受的解决方案来实现相同的效果.例如:
>>> [i for i in itertools.repeat('example', 5)]
['example', 'example', 'example', 'example', 'example']
>>> ['example'] * 5
['example', 'example', 'example', 'example', 'example']
>>> list(map(str.upper, itertools.repeat('example', 5)))
['EXAMPLE', 'EXAMPLE', 'EXAMPLE', 'EXAMPLE', 'EXAMPLE']
>>> ['example'.upper()] * 5
['EXAMPLE', 'EXAMPLE', 'EXAMPLE', 'EXAMPLE', 'EXAMPLE']
Run Code Online (Sandbox Code Playgroud)
在任何情况下,它是最合适的解决方案吗?如果是这样,在什么情况下呢?
Ray*_*ger 24
itertools.repeat的主要目的是提供一个常量值流,用于map或zip:
>>> list(map(pow, range(10), repeat(2))) # list of squares
[0, 1, 4, 9, 16, 25, 36, 49, 64, 81]
Run Code Online (Sandbox Code Playgroud)
第二个目的是它提供了一种非常快速的循环固定次数的方法,如下所示:
for _ in itertools.repeat(None, 10000):
do_something()
Run Code Online (Sandbox Code Playgroud)
这比以下更快:
for i in range(10000):
do_something().
Run Code Online (Sandbox Code Playgroud)
前者获胜是因为它需要做的就是更新现有None对象的引用计数.后者失败,因为range()或xrange()需要制造10,000个不同的整数对象.
注意,Guido自己在timeit()模块中使用了这种快速循环技术.请参阅https://hg.python.org/cpython/file/2.7/Lib/timeit.py#l195上的来源:
if itertools:
it = itertools.repeat(None, number)
else:
it = [None] * number
gcold = gc.isenabled()
gc.disable()
try:
timing = self.inner(it, self.timer)
Run Code Online (Sandbox Code Playgroud)
Har*_*wEm 20
该itertools.repeat功能是懒惰; 它只使用一个项目所需的内存.在另一方面,(a,) * n和[a] * n成语在内存中创建对象的n个副本.对于五个项目,乘法习惯可能更好,但如果你不得不重复一些事情,比如一百万次,你可能会注意到资源问题.
尽管如此,很难想象很多静态用途itertools.repeat.但是,作为itertools.repeat一个函数的事实允许您在许多功能应用程序中使用它.例如,您可能有一些库函数func,它在可迭代的输入上运行.有时,您可能预先构建了各种项目的列表.其他时候,您可能只想在统一列表上操作.如果列表很大,itertools.repeat将节省你的记忆.
最后,repeat使itertools文档中描述的所谓"迭代器代数"成为可能.甚至itertools模块本身也使用该repeat功能.例如,以下代码作为等效实现给出itertools.izip_longest(即使实际代码可能用C编写).注意repeat从底部使用七行:
class ZipExhausted(Exception):
pass
def izip_longest(*args, **kwds):
# izip_longest('ABCD', 'xy', fillvalue='-') --> Ax By C- D-
fillvalue = kwds.get('fillvalue')
counter = [len(args) - 1]
def sentinel():
if not counter[0]:
raise ZipExhausted
counter[0] -= 1
yield fillvalue
fillers = repeat(fillvalue)
iterators = [chain(it, sentinel(), fillers) for it in args]
try:
while iterators:
yield tuple(map(next, iterators))
except ZipExhausted:
pass
Run Code Online (Sandbox Code Playgroud)
Joh*_*lla 14
你foo * 5看起来表面上看起来很像itertools.repeat(foo, 5),但它实际上是完全不同的.
如果你写作foo * 100000,翻译必须创建100,000份,foo然后才能给你答案.因此,这是一种非常昂贵且对记忆不友好的操作.
但是如果你编写itertools.repeat(foo, 100000),解释器可以返回一个服务相同函数的迭代器,并且在你需要它之前不需要计算结果 - 比如,在想要知道序列中每个结果的函数中使用它.
这是迭代器的主要优点:它们可以推迟计算列表的一部分(或全部),直到您真正需要答案为止.
| 归档时间: |
|
| 查看次数: |
12298 次 |
| 最近记录: |