Reputation: 1535
Here is the code:
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)))
when I use the two lines that's commented out now (for post in valid_posts(stream): print(post)
) it printed out expected result:
{1, 2, 3}
{1}
but when I use the four lines of print(next(valid_posts(stream)))
it surprising print these:
{1, 2, 3}
{1, 2, 3}
{1, 2, 3}
{1, 2, 3}
my understanding we can use next()
to call generator and it yields the result one by one till the end, but how come it just repeatedly print the first result in this case? Thanks
Upvotes: 1
Views: 36
Reputation: 13393
When you do for post in valid_posts(stream):
you actually do:
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
In your usage, you call valid_posts
over and over again instead of using the same iterator.
EDIT:
note that you also have severe type errors.
type annotations are only hints, and PyCharm screams to high heavens when I paste your code in.
The fact the annotations are there and the code runs, doesn't mean the code conforms to the annotations.
Upvotes: 2