The return value of your iterator function is used as the argument to the StopIteration
that it raises when it terminates:
>>> it = gen_test()
>>> next(it)
0
>>> next(it)
1
>>> next(it)
2
>>> next(it)
3
>>> next(it)
4
>>> next(it)
5
>>> next(it)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
StopIteration: [0, 1, 2, 3, 4, 5]
Only the first StopIteration
gets the specified value. Further attempts to iterate an empty generator will raise an empty exception:
>>> next(it)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
StopIteration
You can extract the return value from a normal run of the iterator by avoiding for
loops and trapping the exception yourself:
it = gen_test()
while True:
try:
x = next(it)
# Do the stuff you would normally do in a for loop here
except StopIteration as e:
ret = e.value
break
print(ret)
All this is an awkward approach given that you have to decide between not using for
loops and not being able to return your accumulated data. Assuming that you're not OK with trying to accumulate the data externally (e.g. just doing list(gen_test())
), you can make your generator's state publicly accessible by using a class:
class gen_test:
def __init__(self):
self.l = []
self.it = iter(range(6))
def __iter__(self):
return self
def __next__(self):
i = next(self.it)
self.l.append(i)
return i
Now you can do something like
>>> it = gen_test()
>>> for x in it:
... print(x)
0
1
2
3
4
5
>>> print(it.l)
[0, 1, 2, 3, 4, 5]
self
)? – Paintyreturn
and ayield
in the same function returns an error in py2 - it's a;llowed in py3 but for specific use-cases with co-routines. See this question for a good summary of the mechanisms behind this: #26596395 – Juvenalreturn
statement, but that they want to get the value ofl
somehow and are asking how. – Painty