社区所有版块导航
Python
python开源   Django   Python   DjangoApp   pycharm  
DATA
docker   Elasticsearch  
aigc
aigc   chatgpt  
WEB开发
linux   MongoDB   Redis   DATABASE   NGINX   其他Web框架   web工具   zookeeper   tornado   NoSql   Bootstrap   js   peewee   Git   bottle   IE   MQ   Jquery  
机器学习
机器学习算法  
Python88.com
反馈   公告   社区推广  
产品
短视频  
印度
印度  
Py学习  »  Python

解锁Python生成器:双向通信和send()方法

新语数据故事汇 • 1 年前 • 415 次点击  

我们在短文《一文带您理解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 这行代码:

  • 正常生成值 4

  • 检查是否使用 .send() 方法向生成器发送了任何内容

  • 如果使用 .send() 发送了内容,x 将取该值

  • 如果未发送任何内容,x 将为 None

在不使用 .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))

  • 最后我们仍然生成了3个值:4、5和6,

  • 就像 yield 4,代码行 x = yield 4 仍然会生成4

  • 因为没有使用 .send(),x 一直都是 None

向生成器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:        # yield n, and check if we .send() anything        value_from_send = yield n
if value_from_send is not None: # if we .send() something, replace n n = value_from_send else: # if we don't .sned() anything, just add 1 to n 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() 方法可以让你向生成器输入内容,从而完全控制生成器函数的迭代。这对于处理复杂的数据流和控制结构非常有用。此外,许多现有的生产代码使用了这种方法,因此掌握它是必需的。

Python社区是高质量的Python/Django开发社区
本文地址:http://www.python88.com/topic/171506
 
415 次点击