Reputation: 22244
Please help understand why the two cases act differently although both use a generator (i for i in range(5))
.
>>> print(i for i in range(5))
<generator object <genexpr> at 0x7fc409c02900>
>>> print(*(i for i in range(5)))
0 1 2 3 4
>>> print(*(i for i in range(5)), 5)
0 1 2 3 4 5
>>> _r = (i for i in range(5))
>>> print(_r)
<generator object <genexpr> at 0x7fc409c029e0>
>>> print(*_r)
0 1 2 3 4
>>> print(*_r, 5)
5
>>> print(*(_r), 5)
5
Upvotes: 2
Views: 73
Reputation: 13106
When you use the *
operator on a generator expression (or any iterator for that matter), it consumes it:
my_iterator = (i for i in range(3))
second_iterator = iter(list(range(3)))
# splat operator consumes the generator expression
print(*my_iterator)
0 1 2
print(*my_iterator, "Empty!")
Empty!
# splat operator also consumes the iterator
print(*second_iterator)
0 1 2
print(*second_iterator, "Also empty!")
Also empty!
You'd need to recreate it to re-use it, which is what you're doing in your first example:
s = (i for i in range(3))
print(*s)
0 1 2
# You create a new generator expression/iterator
s = (i for i in range(3))
print(*s)
0 1 2
# And so it isn't empty
# same with the shorthand
print(*(i for i in range(3))
0 1 2
range
Since I've used range
for this example, it's important to note that range
doesn't share this behavior, but an iterator over range
does:
x = range(3)
print(*x)
0 1 2
print(*x)
0 1 2
# the range object isn't consumed and can be re-used
a = iter(x)
print(*a)
0 1 2
print(*a)
# prints nothing because `a` has been exhausted
More detail can be found in this answer
Upvotes: 2