Python系列(七):用栗子带你深入了解生成器的send()方法

一.问题引入

在Python中,可以使用生成器来一次返回单个元素,从而可以避免大量占用内存。下面例子中计算房价函数house_price便是一个生成器的栗子,该函数接收两个参数,其中unit_price表示每平方米单价,areas是售卖的房子的面积。

def house_price(unit_price ,areas):
    for area in areas:
        yield unit_price * area


unit_price = 1
areas = [100, 120, 110, 180]
for price in house_price(unit_price, areas):
    print(f"Price: {price}")
"""
Price: 100
Price: 120
Price: 110
Price: 180
"""

但是上述函数无法解决一个问题:在生成器调用的过程中,我们想更改计算房价的每平方米单价。因此我们需要一种方法可以更改生成器每次迭代的unit_price参数值,这个需求可以做到吗?但是的肯定可以。生成器的send()方法就可以解决这个问题。

二.send()方法详细介绍

生成器的send()方法可以往生成器发送一个值并返回生成器生成的下一个值,下面举个简单的栗子来简单介绍下该方法。

def my_generator():
    receive = yield 3
    yield f"{receive}"

myg = my_generator()
print(myg.send(None)) # print(next(myg))与其作用是等同的
# 3
print(myg.send(5))
# 5

首先,解释下receive = yield 3这行代码,这行代码可以拆成两部分来看,即yield 3receive = yield,前者表示生成一个新的值,后者指接收send()方法传过来的值。在执行顺序上,调用send()方法后会yield 3,当再次调用next()方法时才会完成receive的赋值

send()方法会引发一次next()方法的调用。

然后,再解释下为啥需要myg.send(None),这是send()方法的低层实现硬性规定的,当首次执行时不允许带有参数,下面的对应该部分的低层源码:

if (f->f_lasti == -1) { // f_lasti==-1 代表首次执行
    if (arg && arg != Py_None) { // 首次执行不允许带有参数
        PyErr_SetString(PyExc_TypeError,
                        "can't send non-None value to a "
                        "just-started generator");
        return NULL;
    }
}

在上述栗子中,若去掉myg.send(None),则会报错:TypeError: can't send non-None value to a just-started generator

三.问题解决

有了send()方法,我们现在给出第一节中问题的解决方案:

def house_price(areas):
    unit_price = yield # 接收初始的unit_price
    for area in areas:
        unit_price = yield unit_price * area


unit_prices = [1, 2, 3, 1]
areas = [100, 120, 110, 180]
hp = house_price(areas)
hp.send(None) # 启动生成器
for unit_price in unit_prices:
    cur_price = hp.send(unit_price)
    print(f"Price: {cur_price}")
"""
Price: 100
Price: 240
Price: 330
Price: 180
"""

可以看到通过send()方法,我们可以为每个交易指定一个房价。

结语

从前面的介绍可以看出:send()方法提供了调用者与生成器间的通信机制,通过该机制我们可以进行一些特殊操作,当然这也要视需求而定。

参考资料:

以上便是本文的全部内容,要是觉得不错的话,可以点个赞或关注一下博主,你们的支持是博主创作的不竭动力,当然要是有问题的话也敬请批评指正!!!

  • 4
    点赞
  • 18
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

斯曦巍峨

码文不易,有条件的可以支持一下

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值