Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Assigning (yield) to a variable

Tags:

python

yield

First of all, I'd like to mention that I am not particularly familiar with Python. I have recently been forced to familiarise myself with a code sample that's left my jaws ajar, and I have been unable to "translate" it. The various documents and articles I've taken a look at have not helped either:

  • What does the "yield" keyword do?
  • The Python yield keyword explained
  • The yield statement
  • Yield expressions

Here's a shortened-down version of the function in question:

@coroutine
def processMessage(receiver):
    global userID
    #...
    while True:
        msg = (yield)
        try:
            #...
        except Exception as err:
            #...

I cannot understand what it does and am thus not able to "walk through" the code. My questions are "What does this function do?" and "What sequences does this function follow?"

The line that throws me off is msg = (yield). I have no idea what it's trying to achieve. Intuition tells me it simply grabs new messages as they come through, but I fail to understand why. If anyone knows and if I have provided enough information, I'd really appreciate an explanation.

The Try clause:

if msg['event'] == 'message' and 'text' in msg and msg['peer'] is not None:
    if msg['sender']['username'] == username:
        userID = msg['receiver']['peer_id']
        config.read(fullpath + '/cfg/' + str(userID) + '.cfg')
        if config.has_section(str(userID)):
            log('Config found')
            readConfig()
            log('Config loaded')
        else:
            log('Config not found')
            writeConfig()
            log('New config created')
    if 'username' in msg['sender']:
        parse_text(msg['text'], msg['sender']['username'], msg['id'])

P.S. receiver is a socket receiver.

like image 920
Pyromonk Avatar asked Mar 03 '18 05:03

Pyromonk


1 Answers

The syntax variable = (yield some_value) in a generator does the following:

  • it returns some_value to the code that invoked it (via next or send);
  • when it is next invoked (via .next or .send(another_value)) it assigns another_value to variable and continues execution.

For example, suppose you have a generator function:

>>> def f():
...     while True:
...         given = (yield)
...         print("you sent me:", given)
...

Now, lets call f. That returns us a generator.

>>> g = f()

The very first time we use the generator we cannot send it data

>>> next(g)

At this point it just evaluated the yield ... when we now call .send it will continue from that point, assigning the data we have sent it to the variable given

>>> g.send("hello")
('you sent me:', 'hello')
>>> g.send("there")
('you sent me:', 'there')

In your particular sample code, you have a generator that is:

  • being given a message to process from outside ... something will be calling .send(some_msg);
  • it will be processing that message and then yielding back to the outside caller, which will then feed it another message.
like image 125
donkopotamus Avatar answered Oct 09 '22 07:10

donkopotamus