2012-06-12 8 views
5

リストオブジェクトとisliceオブジェクトの両方が反復可能ですが、なぜこの結果が異なるのでしょうか。ここitertoolsライブラリのtee関数

r = [1, 2, 3, 4]    
i1, i2 = tee(r) 
print [e for e in r if e < 3] 
print [e for e in i2] 
#[1, 2] 
#[1, 2, 3, 4] 


r = islice(count(), 1, 5)   
i1, i2 = tee(r) 
print [e for e in r if e < 3] 
print [e for e in i2] 
#[1, 2] 
#[] 

答えて

14

問題がtee()あなたは、元のイテレータからそれらを消費し始める場合、正しく機能することはできません、元のイテレータから値を消費する必要があるということです。あなたのリストの例では、反復は単に再び始まります。ジェネレータの例では、それは使い尽くされ、それ以上の値は生成されません。

これは十分に文書化されています

ティーたら()は、元のiterableを他の場所で使用すべきではない、分割をしました。さもなければ、iterableはteeオブジェクトに通知されることなく進歩する可能性があります。

Source

編集リストと発電機の間の差でポイントを説明するために:あなたのリストの内包表記で

>>> from itertools import islice, count 
>>> a = list(range(5)) 
>>> b = islice(count(), 0, 5) 
>>> a 
[0, 1, 2, 3, 4] 
>>> b 
<itertools.islice object at 0x7fabc95d0fc8> 
>>> for item in a: 
...  print(item) 
... 
0 
1 
2 
3 
4 
>>> for item in a: 
...  print(item) 
... 
0 
1 
2 
3 
4 
>>> for item in b: 
...  print(item) 
... 
0 
1 
2 
3 
4 
>>> for item in b: 
...  print(item) 
... 
>>> 
+0

リストオブジェクトとisliceオブジェクトは同様に動作する必要がありますか? – John

+1

@Johnいいえ、リストをループすると、毎回新しいイテレーターが得られます。つまり、値を取得することができます。 'islice()'を使うとジェネレータが得られます。ジェネレータは一度値を生成してから使い果たします。それを自分で試してみてください。リストを2回ループし、isliceを使ってループを2回繰り返します。動作の違いに注意してください。 –

+0

@ John 2つの例を同様に動作させるには、 'r = [1,2,3,4]'ではなく 'r = iter([1,2,3,4])'を使います。 – clacke

0

を、あなたはi1rを交換したいです。

関連する問題