Home > Software engineering >  Why can Python's yield statement not be called in a function and also in another function that
Why can Python's yield statement not be called in a function and also in another function that

Time:11-28

I'm new to Python and I am finding the yield statement quite useful. However, something surprised me. Putting multiple yield statements in a function will result in each one being seen in a for var in fn() loop. However, if I execute another function from the initial function that uses the yield statement, that function is not executed. I had just taken the naive approach and just thought it would work.

E.g.

def fn2():
    print("blah")
    yield "you"
    
def fn():
    yield "hi"
    fn2()
    yield "there"
    
for a in fn():
    print('{}'.format(a))

If I were to comment out yield "you", my output would be:

hi
there

If not, it would be:

hi
blah
there

Demo

That there wasn't any warning or error of any sort and it just shrugged and continued to execute was even more surprising than it not working.

What's going on here?

CodePudding user response:

Functions with yield are generators. They always produce an iterable, even if there is only a single yield statement in them.

In order to get the value(s) the function produces, you must iterate.

You could use for v in fn2: yield v, but Python also has a convenience statement: yield from

def fn2():
    print("blah")
    yield "you"
    
def fn():
    yield "hi"
    yield from fn2()
    yield "there"
    
for a in fn():
    print('{}'.format(a))

Python's generators are evaluated lazily. Creating one (in this case "calling fn2") does not start the iteration. That's why it seems that fn2 isn't even called. It is called.

Imagine its return value as a bookmark right before the first line of the function body of fn2. Once you actually start iterating, the "bookmark" will advance to the first yield statement, and so on, until the function ends.

  • Related