
我们在短文《一文带您理解Python生成器(generator):高效利用内存的奥秘》中介绍了python 生成器(generator)的基本用法和特性。Python中的生成器(generator)提供了一种懒加载值的便捷方式,但你了解生成器也支持双向通信吗?接下来将深入探讨强大的“send()”方法和双向通信机制,解锁控制和交互生成器的新可能性。
理解下:x= yield y
我们看一下代码(生成器函数以接受输入)的执行结果:
def test():
x = yield 4
print('x is', x)
x = yield 5
print('x is', x)
x = yield 6
print('x is', x)
for x in test():
print(x,end=" ")

x = yield 4
这行代码:
在不使用 .send() 方法的情况下使用 next
迭代我们的生成器:
def test():
x = yield 4
print('x is', x)
x = yield 5
print('x is', x)
x = yield 6
print('x is', x)
gen = test()
print(next(gen))
print(next(gen))
print(next(gen))

向生成器send数据
看下面示例代码的执行结果:
def test():
x = yield 4
print('x is', x)
x = yield 5
print('x is', x)
x = yield 6
gen = test()
print(next(gen))
print(gen.send(100))
print(next(gen))

注意到我将中间的 next(gen)
替换为 gen.send(100)
。
第一次 next(gen) 发生,生成第一个值。
x = yield 4 运行。这首先生成值 4,并打印 4。
x = yield 4 中的 x 等待我们向它发送某些内容。
gen.send(100) 发生,x = yield 4 中的 x 接收 100。
x 是 100,因此打印 100。
gen.send(100) 还会生成一些内容,因此运行 x = yield 5,并生成值 5 并打印。
x = yield 5 中的 x 等待我们向它发送某些内容。
但我们没有向它发送任何内容。相反,再次发生 next(gen)。
因此,x = yield 5 中的 x 取值 None,并打印 x 是 None。
next(gen) 生成下一个值 6。
向生成器send 多次数据
观察一下代码和执行结果:
def test():
x = yield 4
print('x is', x)
x = yield 5
print('x is', x)
x = yield 6
gen = test()
print(next(gen))
print(gen.send(100))
print(gen.send('apple'))

上述代码中有两个 .send() 语句:
next(gen) 发生,x = yield 4 运行。我们打印 4。
x = yield 4 中的 x 等待我们发送某些内容。
gen.send(100) 发生,x 现在是 100。打印 x 是 100。
gen.send(100) 也会自动生成一些内容,因此 x = yield 5 运行,并打印 5。
gen.send('apple') 发生,x 现在是 'apple'。打印 x 是 'apple'。
gen.send('apple') 也会自动生成一些内容,因此 x = yield 6 运行,并打印 6。
更实际的例子:双向通信,逻辑控制的示例
我们需要一个生成器,它会永远计数 1、2、3、4、5…… 但是,如果我们向它发送一个值,生成器会从该数字继续计数。
def test():
n = 1
while True:
value_from_send = yield n
if value_from_send is not None:
n = value_from_send
else:
n += 1
gen = test()
print(next(gen))
print(next(gen))
print(next(gen))
print(next(gen))
print(next(gen))

如果我们不向生成器 .send() 任何内容,它会从 1 开始打印,并每次增加 1。现在让我们向生成器发送一些数据。
gen = test()
print(next(gen))
print(next(gen))
print(next(gen))
print(gen.send(101))
print(next(gen))
print(next(gen))

正常开始打印 1,然后是 2,然后是 3。
接着我们 .send(101)。
此时,value_from_send 是 101。
if 语句块运行,n 现在是 101。所以我们生成 101。
之后,不再发生 .send(),我们继续以正常的 1 增量计数。
了解 Python 生成器的 send() 方法可以让你向生成器输入内容,从而完全控制生成器函数的迭代。这对于处理复杂的数据流和控制结构非常有用。此外,许多现有的生产代码使用了这种方法,因此掌握它是必需的。