user13
user13

Reputation: 391

How except works for iterators in Python?

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

Answers (3)

MSeifert
MSeifert

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, otherwise StopIteration 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

Jn Liv
Jn Liv

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

jpp
jpp

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

Related Questions