Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

Why can Python's yield statement not be called in a function and also in another function that it calls and why no error reported when attempted?

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:

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

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?

>Solution :

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.

Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading