gpt4 book ai didi

python : Behaviour of send() in generators

转载 作者:太空狗 更新时间:2023-10-30 00:48:43 26 4
gpt4 key购买 nike

我在 python 3 中试验生成器并编写了这个相当人为的生成器:

def send_gen():
print(" send_gen(): will yield 1")
x = yield 1
print(" send_gen(): sent in '{}'".format(x))
# yield # causes StopIteration when left out


gen = send_gen()
print("yielded {}".format(gen.__next__()))

print("running gen.send()")
gen.send("a string")

输出:

    send_gen(): will yield 1
yielded 1
running gen.send()
send_gen(): sent in 'a string'
Traceback (most recent call last):
File "gen_test.py", line 12, in <module>
gen.send("a string")
StopIteration

因此 gen.__next__() 到达行 x = yield 1 并产生 1。我认为 x 将被分配给 None,然后 gen.send() 将查找next yield 语句,因为 x = yield 1 被“使用”,然后 得到一个StopIteration

相反,似乎发生的是 x 被发送“一个字符串”,它被打印出来,然后然后 python 尝试寻找下一个 yield 并获得一个 StopIteration

所以我试试这个:

def send_gen():
x = yield 1
print(" send_gen(): sent in '{}'".format(x))


gen = send_gen()
print("yielded : {}".format(gen.send(None)))

输出:

yielded : 1

但是现在没有错误了。 send() 似乎没有在将 x 分配给

为什么行为略有不同?这与我启动发电机的方式有关吗?

最佳答案

行为没有不同;你从未超越第一个yield在第二个设置中生成器中的表达式。注意 StopIteration 不是错误;这是正常行为,只要生成器结束就会触发预期的信号。在您的第二个示例中,您从未到达生成器的末端。

每当生成器达到 yield表达式,执行暂停在那里,表达式不能在生成器中产生任何东西,直到它被恢复。 gen.__next__()gen.send()都将从该点恢复执行,使用 yield表达式要么生成 gen.send() 传入的值, 或 None .你可以看到 gen.__next__()作为 gen.send(None)如果有帮助的话。这里要意识到的一件事是 gen.send()yield 首先返回发送的值,然后然后生成器继续到下一个yield .

因此,给定您的第一个示例生成器,会发生这种情况:

  1. gen = send_gen()创建生成器对象。代码暂停在函数的最顶部,不执行任何操作。

  2. 您可以调用 gen.__next__()gen.send(None) ;生成器开始并执行直到第一个 yield表达式:

    print("    send_gen(): will yield 1")
    yield 1

    现在执行暂停gen.__next__()gen.send(None)现在调用返回 1 ,由 yield 1 产生的值.因为生成器现在已暂停,所以 x = ...任务还不能发生!只有当发电机再次恢复时才会发生这种情况。

  3. 您调用 gen.send("a string")在您的第一个示例中,不要在第二个示例中进行任何 调用。所以对于第一个例子,生成器函数现在恢复了:

    x = <return value of the yield expression>  # 'a string' in this case
    print(" send_gen(): sent in '{}'".format(x))

    现在函数结束,所以StopIteration提出。

因为您从未在第二个示例中恢复生成器,所以未到达生成器的末尾并且没有 StopIteration引发异常。

请注意,因为生成器从函数的顶部开始,所以没有 yield此时的表达式返回您用 gen.send() 发送的任何内容所以第一个gen.send()值必须始终为 None或引发异常。最好使用明确的 gen.__next__() (或者,更确切地说是一个 next(gen) 函数调用)来“启动”生成器,这样它就会在第一个 yield 处暂停。表达。

关于 python : Behaviour of send() in generators,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36997078/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com