views:

136

answers:

2

I am not a python guy and I am trying to understand some python code. I wonder what the last line of below code does? Is that kind of multiple objects returned? or list of 3 objects returned?

req = SomeRequestBean()
req.setXXX(xxx)
req.YYY = int(yyy)

device,resp,fault = yield req          #<----- What does this mean ?
+4  A: 

the last line is unpacking a tuple from the send method of the coroutine that the displayed code is located in.

that is to say that it occurs in a function:

def coroutine(*args):
    yield None
    req = SomeRequestBean()
    req.setXXX(xxx)
    req.YYY = int(yyy)

    device,resp,fault = yield req  

there is then client code that somewhere that looks something like this.

co = coroutine(*args)
next(co)  # consume the first value so we can start sending.
co.send((device, resp, fault))

a simpler example of this that doesn't involve coroutines is something along the lines of

a, b, c = (1, 2, 3)

or (slightly fancier)

for a, b in zip(['a', 'b'], [1, 2]):
    print a, b

here zip returns tuples that get unpacked to a and b. so one tuple would look like ('a', 1) and then a == 'a' and b == 1.

aaronasterling
+8  A: 

There are two things going on in that line. The easier one to explain is that the yield statement is returning a value which is a sequence, so the commas take values of the sequence and put them in the variables, much like this:

>>> def func():
...     return (1,2,3)
...
>>> a,b,c = func()
>>> a
1
>>> b
2
>>> c
3

Now, the yield statement is used to create a generator, which can return a number of values rather than just one, returning one value each time yield is used. For example:

>>> def func():
...     for a in ['one','two','three']:
...         yield a
...
>>> g = func()
>>> g.next()
'one'
>>> g.next()
'two'
>>> g.next()
'three'

In effect, the function stops at the yield statement, waiting to be asked for the next value before carrying on.

In the example above next() gets the next value from the generator. However, if we use send() instead we can send values back to the generator which are returned by the yield statement back in to the function:

>>> def func():
...     total = 0
...     while True:
...        add = yield total
...        total = total + add
...
>>> g = func()
>>> g.next()
0
>>> g.send(10)
10
>>> g.send(15)
25

Putting this all together we get:

>>> def func():
...     total = 0
...     while True:
...         x,y = yield total
...         total = total + (x * y)
...
>>> g = func()
>>> g.next()
0
>>> g.send([6,7])
42

A generator used in this way is called a coroutine.

Dave Webb