2017-09-02 9 views
1

私たちは、次の発電機や発電機の機能を検討している場合:なぜビルトインITERファンクションジェネレータ関数ジェネレータにジェネレータ関数を使用するためにジェネレータをiterに渡すのはなぜですか?

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] 

と呼ばれなければなりませんの?コードはまだ実行され、正しい値が印刷されます。

+0

その行を削除して、実行するリストを渡すようにしてください。 'take([1、2、3]、2)' –

答えて

2

takeそれが(例えば、発電機など)イテレータまたは(例えば、リスト/タプル/セットのような)容器を受け取るかどうかを知りません。後者の場合、コンテナには.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コールが必要な理由は明らかです。

+0

イテレータは* iterablesです。これは[iterator spec](https://docs.python.org/3/library/stdtypes.html#iterator.__iter__)に必要です。 – user2357112

+0

@ user2357112私は正しい言葉を見つけるのに苦労しています...ここで適切なのは何ですか? –

+1

@cᴏʟᴅscontainersあなたはそれらをコンテナと呼ぶことができます。 –

0

あなたtake機能にlistまたはtupleを渡すと、彼らはnextメソッドを持っていません。あなたnext方法を持っているんlistiteratorを与えるlistiterを使用して

>>> [1, 2, 3].next() # AttributeError: 'list' object has no attribute '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:私の編集をビートしてください。 :-) –

関連する問題