2017-02-16 4 views
1

Рассмотрим следующий пример:Можно ли повторять итераторы только один раз?

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

Безопасно ли использовать тот же итератор дважды?

+0

Было действительно странно, что никто не ответил на этот простой вопрос. Хорошо, в следующий раз я попытаюсь изменить условия поиска. – farsil

+1

Вы заблуждаетесь итераторами и итерами, некоторые итерации могут повторяться много раз (например, '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() не получает никаких дополнительных элементов из него , В общем случае невозможно сбросить итератор, чтобы он мог снова прокручиваться. Для того, чтобы функции foo() правильно поддерживать итераторы, он должен быть переписан так, что итератор циклическое через только один раз, например, путем сохранения элементов из iterator во временную tuple или list:

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

или, если iterator дает большое количество элементов, с помощью тщательно обработки его с помощью for цикла:

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_ 

Это даст правильный результат:

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

Или используйте 'itertools.tee' или преобразуйте его в список для повторного использования. –

Смежные вопросы