неожиданный вывод при использовании next (генератор)

#python #python-3.x #generator

#python #python-3.x #генератор

Вопрос:

Вот код:

 from typing import Any, Generator, List, Set, Union
stream_type = Union[List[Any], str]

def valid_posts(stream: Generator[stream_type, None, None]) -> Set[int]:
    result = set()
    for post in stream():
        if post == "end_of_session":
            yield result
            result = set()       
            continue
        if post[2] == "hello":
            result.add(post[1])    
            

def stream():
    data = [
        [1, 1, "hello"],
        [1, 1, "world"],
        [1, 2, "hello"],
        [1, 2, "world"],
        [1, 3, "hello"],
        [1, 3, "world"],
        [1, 1, "hello"],
        [1, 1, "world"],
        "end_of_session",
        [2, 1, "hello"],
        [2, 1, "world"],
        [2, 2, "world"],
        [2, 2, "world"],
        [2, 3, "world"],
        [2, 3, "world"],
        "end_of_session",
    ]
    for item in data:
        yield item


# for post in valid_posts(stream):
#     print(post)
print(next(valid_posts(stream)))
print(next(valid_posts(stream)))
print(next(valid_posts(stream)))
print(next(valid_posts(stream)))
  

когда я использую две закомментированные строки now ( for post in valid_posts(stream): print(post) ), он выводит ожидаемый результат:

 {1, 2, 3}
{1}
  

но когда я использую четыре строки print(next(valid_posts(stream))) , это удивительно, напечатать эти:

 {1, 2, 3}
{1, 2, 3}
{1, 2, 3}
{1, 2, 3}
  

насколько я понимаю, мы можем использовать next() для вызова generator, и он выдает результат один за другим до конца, но почему в этом случае он просто повторно печатает первый результат? Спасибо

Комментарии:

1. Копирование-вставка этого кода в Pycharm выделяет stream() in for post in stream(): в valid_posts , говоря 'Generator' object is not callable

Ответ №1:

Когда вы это делаете for post in valid_posts(stream): , вы на самом деле делаете:

 vp = valid_posts(stream) # save the iterator returned from valid_posts
print(next(vp))
print(next(vp))
print(next(vp))
print(next(vp))
# ... a until StopIteration is raised
  

В вашем использовании вы вызываете valid_posts снова и снова вместо того, чтобы использовать один и тот же итератор.

РЕДАКТИРОВАТЬ:
обратите внимание, что у вас также есть серьезные ошибки типа.
аннотации типов — это только подсказки, и PyCharm кричит до небес, когда я вставляю ваш код.
Тот факт, что аннотации есть и код выполняется, не означает, что код соответствует аннотациям.

Комментарии:

1. Извините за многочисленные правки, я неправильно понял «основную причину» вашего недопонимания в первый раз…