【发布时间】:2020-01-03 03:18:23
【问题描述】:
像生成器这样的可迭代对象只能迭代一次:
def f():
for i in range(10):
yield i
a = f()
for x in a:
print(x) # prints x
for x in a:
print(x) # prints none
像list 这样的可迭代对象可以迭代多次:
a = list(range(10))
for x in a:
print(x) # prints x
for x in a:
print(x) # prints x
如何判断一个可迭代对象是否只能迭代一次?
这个问题的动机来自itertools.cycle的实现:
def cycle(iterable):
# cycle('ABCD') --> A B C D A B C D A B C D ...
saved = []
for element in iterable:
yield element
saved.append(element)
while saved:
for element in saved:
yield element
如果我们可以判断一个可迭代对象是否只能迭代一次,我们可以使实现更加节省内存:
def cycle(iterable):
it = iterable
if only_iterated_once(iterable):
it = list(iterable)
while True:
for element in it:
yield element
如果参数可以迭代多次,我们不需要保存额外的副本。
【问题讨论】:
-
没有办法判断你是否只知道它是一个可迭代的,但是,所有的 迭代器 都应该只是一次传递。所以,
iter(iterable) is iterable是一个很好的指标,表明它是单通道 -
你有这方面的文件吗?我觉得很奇怪,没有办法说出来。
-
你怎么可能知道?您可以想要以任何方式实现可迭代。您可以阅读 Python 中的迭代器协议来搜索文档。但一般来说,所有正确实现的迭代器都是单程的(虽然这不是由语言强制执行的)。所有内置容器都可以迭代多次。
-
是的,
iterators只是为了简单的通过。不过,我说的是iterable。 -
@youkaichao:迭代器本身是可迭代的。例如
it = iter([]); iter(it) is it。 (此外,“更节省内存”的实现是不正确的......而且也不是更节省内存。它不会在获取值后立即产生值,并且不适用于无限迭代。)跨度>