Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Using for...else in Python generators

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?

like image 593
James Brady Avatar asked Mar 02 '09 19:03

James Brady


People also ask

What is the use of FOR else in Python?

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.

Can we use the else clause for loops in Python?

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.

How do you use for loop yield in Python?

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.

Can we call generator multiple times in Python?

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.


1 Answers

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.

like image 179
Kenan Banks Avatar answered Oct 17 '22 05:10

Kenan Banks