Reputation: 391
Can you explain to me why the except clause has never been executed and print never been called in the example?
def h(lst):
try:
yield from lst
except StopIteration:
print('ST')
t = h([1,2])
next(t)
>>> 1
next(t)
>>> 2
next(t)
>>> Traceback (most recent call last):
File "<ipython-input-77-f843efe259be>", line 1, in <module>
next(t)
StopIteration
Upvotes: 1
Views: 68
Reputation: 152677
The StopIteration
is thrown by next
, not by the yield from
:
next(iterator[, default])
Retrieve the next item from the iterator by calling its
__next__()
method. If default is given, it is returned if the iterator is exhausted, otherwiseStopIteration
is raised.
So you could instead wrap the next
call.
def h(lst):
yield from lst
def next_or_print(it):
try:
next(it)
except StopIteration:
print('ST')
Then you use it like this:
>>> t = h([1,2])
>>> next_or_print(t)
1
>>> next_or_print(t)
2
>>> next_or_print(t)
ST
Note that next
also has a second argument that allows to provide a default instead of the StopIteration
:
>>> t = h([1,2])
>>> next(t, 'ST')
1
>>> next(t, 'ST')
2
>>> next(t, 'ST')
ST
Upvotes: 2
Reputation: 37
def h(lst):
try:
yield from lst
except StopIteration:
print('ST')
t = h([1, 2])
>>> print(t)
<generator object h at 0x7fbf6f08aa40>
The function "h" returns a generator. The statement "yield" as a "return" does nothing, only returns a generator. The exception will not be in that part of the code.
The exception must be transferred to another part of the code, where it will work.
def h(lst):
yield from lst
t = h([1, 2])
next(t)
next(t)
try:
next(t)
except StopIteration:
print('ST')
ST
Upvotes: 0
Reputation: 164693
Your next
calls are outside your h
function and so are not covered by your try
/ except
clause. For comparison, try this:
def h(lst):
yield from lst
t = h([1,2])
Then run repeatedly:
try:
print(next(t))
except StopIteration:
print('ST')
Result:
1
2
'ST'
'ST'
'ST'
...
Upvotes: 2