XD blog

blog page

iterator, python, return, yield


2016-02-26 Don't mix return and yield

When a function uses the keyword yield, it becomes a generator. A second function can accept this generator and produce another one as follows.

def generator(seq):
    for v in range(0,3):
        yield v+1
        
def generator2(gen):
    for r in gen:
        yield r

for v in generator2(generator(3)):
    print(v)

[1]

1
2
3

This is not the only way to write this function. Python 3.5 has introduction keyword yield from.

def generator(seq):
    for v in range(0,3):
        yield v+1

def generator2(gen):
    yield from gen
        
for v in generator2(generator(3)):
    print(v)

[2]

1
2
3

The use of keyword return would give the same result in that case.

def generator(seq):
    for v in range(0,3):
        yield v+1
        
def generator2(gen):
    return gen

for v in generator2(generator(3), False):
    print(v)

[3]

1
2
3

However, it is not recommended to use if you use both return and yield in the same function. The second one works:

def generator(seq):
    for v in range(0,3):
        yield v+1
        
def generator2(gen, b):
    if b :
        return gen
    else:
        for r in gen:
            yield r+1

for v in generator2(generator(3), False):
    print(v)

[4]

2
3
4

But the first one does not work anymore.

def generator(seq):
    for v in range(0,3):
        yield v+1
        
def generator2(gen, b):
    if b :
        return gen
    else:
        for r in gen:
            yield r+1

for v in generator2(generator(3), True):
    print(v)

[5]


You need to use yield from:

def generator(seq):
    for v in range(0,3):
        yield v+1
        
def generator2(gen, b):
    if b :
        yield from gen
    else:
        for r in gen:
            yield r+1

for v in generator2(generator(3), True):
    print(v)

[6]

1
2
3

<-- -->

Xavier Dupré