如果我们考虑以下生成器和生成器函数:
def integers():
"""Infinite sequence of integers."""
i = 1
while True:
yield i
i = i + 1
def take(n, seq):
"""Returns first n values from the given sequence."""
seq = iter(seq)
result = []
try:
for i in range(n):
result.append(seq.next())
except StopIteration:
pass
return result
print take(5, integers()) # prints [1,2,3,4,5]
为什么必须在生成器函数中将内置iter函数调用到生成器?代码仍然运行并在没有它的情况下打印正确的值。
答案 0 :(得分:2)
take
不知道它是接收迭代器(例如生成器)还是容器(例如list / tuple / set)。在后一种情况下,容器没有与它们关联的.next
方法,因此您的代码将失败。你的代码是安全的,而不是冒险,我认为这是一个很好的编程实践。
一个例子(在python3中):
def foo():
yield from [1, 2, 3]
x = iter([1, 2, 3])
y = iter(foo())
print( next(x), next(y) ) # this would be `x.next()` in python2
(1, 1)
在后一种情况下,iter
是多余的,但代码在两种情况下都有效。但是,请考虑:
x = [1, 2, 3]
print(next(x))
TypeError Traceback (most recent call last)
<ipython-input-351-cf05c93171ef> in <module>()
----> 1 print(next(x))
TypeError: 'list' object is not an iterator
应该清楚为什么需要iter
来电。
答案 1 :(得分:0)
如果您将list
或tuple
传递给take
函数,则他们不会使用next
方法。
>>> [1, 2, 3].next() # AttributeError: 'list' object has no attribute 'next'
在iter
上使用list
将为您提供listiterator
,其中包含next
方法。
>>> my_gen = iter([1, 2, 3])
>>> print(my_gen)
<listiterator object at 0x108390a10>
>>> my_gen.next()
1
>>> next(my_gen)
2