2017-02-16 10 views
1

は、次の例を考えてみましょう:イテレータは1回だけ反復できますか?

def foo(iterator): 
    return sum(iterator)/max(iterator) 

は二度同じイテレータを再利用することは安全ですか?

+0

この単純な質問に誰も答えなかったのは本当に不思議でした。さて、次回は検索語を変更しようとします。 – farsil

+1

あなたはタイトルがイテレータとiterablesを混同していますが、いくつかのiterablesは何度も繰り返すことができます( 'lists'のように) –

+0

うーん。質問は重複としてマークされていますが、タイトルを編集する必要がありますか? – farsil

答えて

2

いいえ、安全ではありません。イテレータはシーケンスではありません。ここではそれ自体がイテレータである、発電機を使用してそのfoo()機能で何が起こるかです:

>>> foo(x for x in range(10)) 
Traceback (most recent call last): 
    File "<stdin>", line 1, in <module> 
    File "<stdin>", line 1, in foo 
ValueError: max() arg is an empty sequence 

イテレータがその終わりにすでにあるためであるsum()はその仕事を終えた後、そのmax()は、それからの追加アイテムを取得されていない場合。一般的に、反復子をリセットして再循環させることはできません。場合は、

def foo(iterator): 
    iterable = list(iterator) 
    return sum(iterable)/max(iterable) 

か:適切イテレータをサポートするfoo()関数のためには、イテレータは一度だけに循環されるように、一時的tupleまたはlistiteratorから項目を保存することで、例えば、書き換える必要があります

def foo(iterator): 
    # allows iterables like lists or tuples to be passed as arguments 
    iterator = iter(iterator) 

    try: 
     max_ = next(iterator) 
     sum_ = max_ 
    except StopIteration: 
     # iterator yields no items, return some default value 
     return 0.0 

    for element in iterator: 
     sum_ += element 
     max_ = max(max_, element) 

    return sum_/max_ 

これは、適切な結果を生成します:iteratorforループを使用して、それを扱う慎重により、多数のアイテムを生成します

>>> foo(x for x in range(10)) 
5.0 
+2

または 'itertools.tee'を使うか、リストに変換して再利用してください。 –

関連する問題