Что означает этот синтаксис Python? - PullRequest
6 голосов
/ 14 сентября 2010

Я не парень по Python, и я пытаюсь понять некоторый код Python.Интересно, что делает последняя строка кода ниже?Этот вид нескольких объектов возвращается?или список из 3 объектов возвращен?

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

device,resp,fault = yield req          #<----- What does this mean ?

Ответы [ 2 ]

9 голосов
/ 14 сентября 2010

В этой строке происходит две вещи. Проще объяснить, что оператор yield возвращает значение, являющееся последовательностью, поэтому запятые принимают значения последовательности и помещают их в переменные, примерно так:

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

Теперь оператор yield используется для создания генератора , который может возвращать не одно, а несколько значений, возвращая одно значение каждый раз, когда используется yield. Например:

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

По сути, функция останавливается на операторе yield, ожидая, когда будет запрошено следующее значение, прежде чем продолжить.

В приведенном выше примере next() получает следующее значение от генератора. Однако, если мы вместо этого используем send(), мы можем отправить значения обратно в генератор, которые возвращаются оператором yield обратно в функцию:

>>> 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

Собрав все это вместе, мы получим:

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

Генератор, используемый таким образом, называется сопрограммой .

4 голосов
/ 14 сентября 2010

последняя строка распаковывает кортеж из метода send сопрограммы, в которой находится отображаемый код.

, то есть, это происходит в функции:

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

    device,resp,fault = yield req  

есть клиентский код, который где-то выглядит примерно так:

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

Более простой пример этого, который не включает сопрограммы, - это что-то вроде

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

или (немного причудливее)

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

здесь zip возвращает кортежи, распакованные в a и b.поэтому один кортеж будет выглядеть как ('a', 1), а затем a == 'a' и b == 1.

...