Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What does a plain yield keyword do in Python?

Tags:

python

yield

According to the Python documentation the yield keyword can take an "expression_list", but it is optional:

yield_expression ::=  "yield" [expression_list]

I can find no examples of such usage, either in the Python docs, in any of the answers to What does the yield keyword do in Python, nor from generally reading around the web.

If yield is used without an expression_list then I guess that the resulting method cannot be useful as a generator, so are there other scenarios where a plain yield might be useful?

like image 282
jalanb Avatar asked Mar 05 '15 14:03

jalanb


People also ask

What does yield keyword do in Python?

yield keyword is used to create a generator function. A type of function that is memory efficient and can be used like an iterator object. In layman terms, the yield keyword will turn any expression that is given with it into a generator object and return it to the caller.

What does yield do in programming?

In computer science, yield is an action that occurs in a computer program during multithreading, of forcing a processor to relinquish control of the current running thread, and sending it to the end of the running queue, of the same scheduling priority.

Should I use yield in Python?

We should use yield when we want to iterate over a sequence, but don't want to store the entire sequence in memory. Yield are used in Python generators. A generator function is defined like a normal function, but whenever it needs to generate a value, it does so with the yield keyword rather than return.

What does yield do in Pytest?

In Python, the yield keyword is used for writing generator functions, in pytest, the yield can be used to finalize (clean-up) after the fixture code is executed.


2 Answers

Although they're almost always used as simple generators, yield enables fully-fledged coroutines.

Besides being used to send values out of a generator / co-routine, yield can also receive values, with the effect of coordinating the execution different co-routines. Thus, you don't need expression_list if you only want to coordinate or receive values.

Here's a simple example:

def infini_printer():
    while True:
        received = yield # get the received value into a variable
        print(received)

printer = infini_printer()
printer.next()              # returns None, since we didn't specify any expression after yield
printer.send("foo")         # prints "foo"
like image 128
loopbackbee Avatar answered Oct 06 '22 01:10

loopbackbee


It works more like how a return with no arguments simply returns None.

>>> def foobar():
...    for i in range(10):
...        yield
>>>
>>> for token in foobar():
...    print(token)
None
None
None
None
None
None
None
None
None
None

Where this is going to be more common is when you are writing coroutines where there is important work you are doing in a function, and the yield point is simply the 'pause' point -- waiting for someone or something to call next or send but you may not have anything of concern to return.

>>> def do_important_work():
...
...    do_it = True
...    state = 0
...    while do_it:
...        print(state)
...        state += 1
...        # do some more important work here ...
...        do_it = yield
...
>>> worker = do_important_work()
... 
>>> worker.next()
>>> worker.send(True)
>>> worker.send(True)
>>> worker.send(True)
0
1
2
3

I think yield was simply designed so you were not forced to return a value, just like how return is designed.

like image 34
Andrew Carter Avatar answered Oct 06 '22 00:10

Andrew Carter