Python yield 使用浅析

本文深入探讨Python中的生成器概念及其应用场景,并通过具体实例详细解释yield关键字的作用及如何使用。文章对比了列表与生成器在内存使用上的区别,演示了如何利用yield实现高效的迭代操作。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Python关键字yield的作用是什么?用来干什么的? 回答: 为了理解什么是 yield,你必须理解什么是生成器。在理解生成器之前,让我们先走近迭代。

可迭代对象

当你建立了一个列表,你可以逐项地读取这个列表,这叫做一个可迭代对象:

>>> mylist = [1, 2, 3]
>>> for i in mylist :
...    print(i)
1
2
3

mylist 是一个可迭代的对象。当你使用一个列表生成式来建立一个列表的时候,就建立了一个可迭代的对象:

>>> mylist = [x*x for x in range(3)]
>>> for i in mylist :
...    print(i)
0
1
4

所有你可以使用 for .. in .. 语法的叫做一个迭代器:列表,字符串,文件……你经常使用它们是因为你可以如你所愿的读取其中的元素,但是你把所有的值都存储到了内存中,如果你有大量数据的话这个方式并不是你想要的。

生成器

生成器是可以迭代的,但是你 只可以读取它一次 ,因为它并不把所有的值放在内存中,它是实时地生成数据:

>>> mygenerator = (x*x for x in range(3))
>>> for i in mygenerator :
...    print(i)
0
1
4

看起来除了把 [] 换成 () 外没什么不同。但是,你不可以再次使用 for i in mygenerator , 因为生成器只能被迭代一次:先计算出0,然后继续计算1,然后计算4,一个跟一个的…

yield关键字

yield 是一个类似 return 的关键字,只是这个函数返回的是个生成器。

>>> def createGenerator() :
...    mylist = range(3)
...    for i in mylist :
...        yield i*i
...
>>> mygenerator = createGenerator() # create a generator
>>> print(mygenerator) # mygenerator is an object!
<generator object createGenerator at 0xb7555c34>
>>> for i in mygenerator:
...     print(i)
0
1
4

实例:斐波那契数列

斐波那契数列是一个非常简单的递归数列,除次一个和第二个之外,任意一个数都可由前两个数相加得到,

例一: 初级写法

结果没有问题,直接在 fab 函数中用 print 打印数字会导致该函数可复用性较差,因为 fab 函数返回 None,其他函数无法获得该函数生成的数列(不带有return功能)

def fab(max): 
    n, a, b = 0, 0, 1 
    while n < max: 
        print b 
        a, b = b, a + b 
        n = n + 1

 >>> fab(5) 
 1 
 1 
 2 
 3 
 5

例二: 初级写法并且有return功能

该写法弥补了例一的弊端,在犹豫return的是一个list会占用大量的内存.如果要控制内存使用 最好还是不要用list.例似range和xrange的区别

def fab(max): 
    n, a, b = 0, 0, 1 
    L = [] 
    while n < max: 
        L.append(b) 
        a, b = b, a + b 
        n = n + 1 
    return L

 >>> for n in fab(5): 
 ...     print n 
 ... 
 1 
 1 
 2 
 3 
 5

例三: 类方法编写迭代器

改方法配合使用__iter__和next来达到生成迭代器的方法,但写法过于复杂

class Fab(object): 

    def __init__(self, max): 
        self.max = max 
        self.n, self.a, self.b = 0, 0, 1 

    def __iter__(self): 
        return self 

    def next(self): 
        if self.n < self.max: 
            r = self.b 
            self.a, self.b = self.b, self.a + self.b 
            self.n = self.n + 1 
            return r 
        raise StopIteration()

 >>> for n in Fab(5): 
 ...     print n 
 ... 
 1 
 1 
 2 
 3 
 5

例四: yield版

和第一版对比仅仅只是把print修改成yield即可.每次执行到yield就return一个生成器.下次再循环时从yiled后面开始执行直到再次执行到yield return一个生成器。

def fab(max): 
    n, a, b = 0, 0, 1 
    while n < max: 
        yield b 
        a, b = b, a + b 
        n = n + 1 

>>> for n in fab(5): 
 ...     print n 
 ... 
 1 
 1 
 2 
 3 
 5

另一个yield的例子:

def read_file(fpath): 
    BLOCK_SIZE = 1024 
    with open(fpath, 'rb') as f: 
        while True: 
            block = f.read(BLOCK_SIZE) 
            if block: 
                yield block 
            else: 
                return
223916_bL9y_2663968.jpg
内容概要:本文深入探讨了DevOps流程落地中自动化测试与监控体系的构建,强调二者是保障软件质量和系统稳定性的重要支柱。自动化测试涵盖从单元测试到端到端测试的全流程自动化,而监控体系则通过实时采集和分析系统数据,及时发现并解决问题。文章介绍了测试金字塔模型的应用、监控指标的分层设计、测试与生产环境的一致性构建以及告警策略的精细化设置等核心技巧。此外,还提供了基于Python和Prometheus的具体代码案例,包括自动化接口测试脚本和监控指标暴露的实现,展示了如何在实际项目中应用这些技术和方法。 适合人群:对DevOps有一定了解,从事软件开发、运维或测试工作的技术人员,特别是那些希望提升自动化测试和监控能力的从业者。 使用场景及目标:①高并发业务系统中,模拟大规模用户请求,验证系统抗压能力和稳定性;②关键业务流程保障,确保金融交易、医疗数据处理等敏感业务的合规性和可追溯性;③微服务架构系统下,通过契约测试和分布式链路追踪,保证服务间的兼容性和故障快速定位。 阅读建议:本文不仅提供了理论指导,还有详细的代码示例,建议读者结合自身项目的实际情况,逐步实践文中提到的技术和方法,特别是在构建自动化测试框架和监控系统时,关注环境一致性、测试覆盖率和性能指标等方面。
内容概要:该论文针对电熔镁砂熔炼过程的强非线性特性,提出了一种带输出补偿的PID控制方法。电熔镁炉以三相电机转动方向和频率为输入,三相电极电流为输出,模型参数如埋弧电阻率、熔池电阻率和高度会随熔炼过程变化。作者采用线性模型加未知高阶非线性项描述系统,设计了消除非线性项及其变化率的补偿器,结合一步最优前馈控制律和调节律确定PID参数。仿真和工业应用表明,该方法能在动态特性随机变化时,将电流跟踪误差控制在目标范围内。论文还详细介绍了控制器的设计、实现及仿真验证过程,包括非线性补偿、抗积分饱和、自适应补偿增益等改进措施,以及工业应用中的关键技术如参数辨识、安全保护机制等。 适用人群:具备一定自动化控制理论基础,从事工业控制系统设计与优化的研发人员和工程师。 使用场景及目标:①解决电熔镁砂熔炼过程中由于参数时变和非线性带来的控制难题;②提高电流控制精度,降低单吨能耗,提升生产效率和产品质量稳定性;③适用于类似强非线性、时变特性的工业过程控制领域。 其他说明:该控制方法通过系统性的非线性补偿设计和在线参数调整,相比传统PID控制,能显著降低电流跟踪误差,减少能耗。实际应用中需根据具体电熔镁炉特性调整模型参数和补偿系数,确保控制性能最优。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值