Python:产量和产量分配

时间:2015-08-20 21:07:02

标签: python yield assignment-operator

此代码(包括赋值和yield运算符)如何工作?结果相当混乱。

def test1(x): 
    for i in x:
        _ = yield i 
        yield _
def test2(x): 
    for i in x:
        _ = yield i 

r1 = test1([1,2,3])
r2 = test2([1,2,3])
print list(r1)
print list(r2)

输出:

[1, None, 2, None, 3, None] 
[1, 2, 3]

3 个答案:

答案 0 :(得分:15)

赋值语法(" yield表达式")允许您将生成器视为基本协程。

首先在PEP 342中提出并在此处记录:https://docs.python.org/2/reference/expressions.html#yield-expressions

使用生成器的客户端代码可以使用其send()方法将数据传回发生器。可以通过赋值语法访问该数据。

send()也会进行迭代 - 因此它实际上包含next()来电。

使用您的示例,这就是使用couroutine功能的原因:

>>> def test1(x):
...     for i in x:
...         _ = yield i
...         yield _
...
>>> l = [1,2,3]
>>> gen_instance = test1(l)

>>> #First send has to be a None
>>> print gen_instance.send(None)
1
>>> print gen_instance.send("A")
A
>>> print gen_instance.send("B")
2
>>> print gen_instance.send("C")
C
>>> print gen_instance.send("D")
3
>>> print gen_instance.send("E")
E
>>> print gen_instance.send("F")
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
StopIteration

请注意,由于每次循环迭代中的第二个yield没有捕获发送的数据,因此某些发送会丢失。

修改 忘了解释你的例子中产生的None

来自https://docs.python.org/2/reference/expressions.html#generator.next

  

当使用next()方法恢复生成器函数时,当前   yield表达式始终计算为None。

使用迭代语法时使用

next()

答案 1 :(得分:4)

_ = yield i 
yield _

首先yieldi引用的值,例如1。然后它产生yield操作返回的值,即None。它在循环的每次迭代中执行此操作。

for i in x:
    _ = yield i

这只是yield i引用的值,例如1,然后进入循环的下一次迭代,生成2,然后生成3

return不同,yield关键字可用于表达式:

x = return 0 # SyntaxError
x = yield 0 # perfectly fine

现在,当解释器看到yield时,它将生成指示的值。但是,当它执行此操作时,该操作将返回值None,就像mylist.append(0)print('hello')returnNone一样。当您将结果分配给_等引用时,您需要保存None

因此,在第一个片段中,您将产生一个对象,然后保存&#34;结果&#34;那个yield操作是None,然后是yield None。在第二个片段中,您生成一个对象,然后保存&#34;结果&#34;那个yield操作,但你从不yield结果,所以None没有出现在输出中。

请注意yield永远不会返回None - 这就是您使用send()发送给生成器的内容。因为在这种情况下,这不是什么,所以你得到None。有关send()的更多信息,请参阅this answer

答案 2 :(得分:3)

要扩展TigerhawkT3的答案,导致yield操作在代码中返回Shard shardYouAreAfter = null; String streamName = "YourStreamName"; StreamDescription streamDesc = client.describeStream(streamName).getStreamDescription(); List<Shard> shards = streamDesc.getShards(); for(Shard shard : shards){ BigInteger startingHashKey = new BigInteger(shard.getHashKeyRange().getStartingHashKey()); BigInteger endingHashKey = new BigInteger(shard.getHashKeyRange().getEndingHashKey()); if(startingHashKey.compareTo(biPartKey) <= 0 && endingHashKey.compareTo(biPartKey) >=0) { shardYouAreAfter = shard; break; } } 的原因是因为None没有将任何发送到发电机。试试这个:

list(r1)

输出:

def test1(x):
    for i in x:
        _ = yield i
        yield _


r1 = test1([1, 2, 3])

for x in r1:
    print('   x', x)
    print('send', r1.send('hello!'))

这是一个有点制造的例子,将值发送到生成器可能很有用:

   x 1
send hello!
   x 2
send hello!
   x 3
send hello!

输出:

def changeable_count(start=0):
    current = start
    while True:
        changed_current = yield current
        if changed_current:
            current = changed_current
        else:
            current += 1

counter = changeable_count(10)

for x in range(20):
    print(next(counter), end=' ')

print()
print()

print('Sending 51, printing return value:', counter.send(51))
print()

for x in range(20):
    print(next(counter), end=' ')

print()
print()

print('Sending 42, NOT printing return value')
print()

counter.send(42)

for x in range(20):
    print(next(counter), end=' ')

print()