2017-09-02 97 views
1

如果我們考慮以下發電機和發電機功能:爲什麼通過發電機進入發電機使用其發電機功能?

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

嘗試刪除該行並傳遞一個列表。 'take([1,2,3],2)' –

回答

2

take不知道它是否接收到一個迭代(例如發電機)或容器(如列表/元組/組)。在後一種情況下,容器沒有與它們關聯的方法,所以你的代碼將失敗。你的代碼玩起來很安全,而不是冒險,我認爲這是很好的編程習慣。


一個例子(在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呼叫應當明確。

+0

迭代器*是* iterables。這是[iterator spec]所必需的(https://docs.python.org/3/library/stdtypes.html#iterator.__iter__)。 – user2357112

+0

@ user2357112我在努力尋找正確的措辭......這裏適合什麼? –

+1

@cᴏʟᴅsᴘᴇᴇᴅ您可以將它們稱爲容器。 –

0

如果您將listtuple傳遞給您的take函數,則它們不會有next方法。

>>> [1, 2, 3].next() # AttributeError: 'list' object has no attribute 'next' 

list使用iter會給你一個listiterator,它確實有next方法。

>>> my_gen = iter([1, 2, 3]) 
>>> print(my_gen) 
<listiterator object at 0x108390a10> 
>>> my_gen.next() 
1 
>>> next(my_gen) 
2 
+0

'listiterator'是一個迭代器,但不是一個生成器 – vaultah

+0

@vaultah:打我到我的編輯。 :-) –