I'm a big fan of Python's for...else syntax - it's surprising how often it's applicable, and how effectively it can simplify code.
However, I've not figured out a nice way to use it in a generator, for example:
def iterate(i):
for value in i:
yield value
else:
print 'i is empty'
In the above example, I'd like the print
statement to be executed only if i
is empty. However, as else
only respects break
and return
, it is always executed, regardless of the length of i
.
If it's impossible to use for...else
in this way, what's the best approach to this so that the print
statement is only executed when nothing is yielded?
Python allows the else keyword to be used with the for and while loops too. The else block appears after the body of the loop. The statements in the else block will be executed after all iterations are completed. The program exits the loop only after the else block is executed.
In most of the programming languages (C/C++, Java, etc), the use of else statement has been restricted with the if conditional statements. But Python also allows us to use the else condition with for loops. The else block just after for/while is executed only when the loop is NOT terminated by a break statement.
yield in Python can be used like the return statement in a function. When done so, the function instead of returning the output, it returns a generator that can be iterated upon. You can then iterate through the generator to extract items. Iterating is done using a for loop or simply using the next() function.
Generators can help you write reusable and scalable Python code, but the problem is that complicated processing often requires using the same data multiple times. However, the issue with generators is that they exhaust themselves, meaning they can produce results only once.
You're breaking the definition of a generator, which should throw a StopIteration exception when iteration is complete (which is automatically handled by a return statement in a generator function)
So:
def iterate(i):
for value in i:
yield value
return
Best to let the calling code handle the case of an empty iterator:
count = 0
for value in iterate(range([])):
print value
count += 1
else:
if count == 0:
print "list was empty"
Might be a cleaner way of doing the above, but that ought to work fine, and doesn't fall into any of the common 'treating an iterator like a list' traps below.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With