Python yield,python的yield用法
产量?
一般来说,yield和return关键字差不多,但是工作方式却大不相同。要完全理解yield是如何工作的,首先需要理解什么是生成器。为了理解什么是生成器,我们必须理解什么是iterable。
首先,本文给出了一种理解包含yield关键字的函数/代码的简便方法。然后讨论可重写和生成器。在此基础上,讨论了收益率的结构。
理解葵花宝典的产量关键词
当遇到包含yield的函数的代码时,可以通过以下方式轻松读取该函数:
在函数的开头插入result=[]。
用result.append(表达式)替换所有产量表达式
在函数末尾插入返回结果
此时,代码就变成了没有收益的普通代码。重读代码可以很容易理解功能。
对比原代码,理解yield的含义。
虽然可以这样理解函数的逻辑,但实际上yield的工作方式与它处理列表替换的方式有很大不同。在某些情况下,从内存和运行时的角度来看,使用yield关键字更有效。在某些情况下,即使原始代码工作正常,使用此方法而不是yield也可能导致无限循环。
可擦除和迭代器
对于我列表中的ele:
循环本体
在Python中,所有可以在for.in .模式中循环的对象都是可迭代的。例如列表、字符串、文件等。或者,在Python中,所有实现__iter(__方法的类实例都是可迭代的。_ _迭代器(_ _方法必须返回迭代器。迭代器是实现next()方法的对象。在一个类中同时实现__iter__和next是合法的。在这种情况下,__ITER___只是返回自我。这在简单的应用中是没有问题的。但是,如果试图同时用两个或更多迭代器循环同一个对象,这种模式就不符合要求。
这意味着iterable是任何可以通过调用iterator()方法获得iterator的对象。迭代器是用于循环可迭代对象的对象。
Python上mylist中for ele的工作模式如下。
你将得到我的列表迭代器。调用ITER(我的名单)。这个方法返回Python3中next))方法实现__next) _)的对象(迭代器)。
使用这个迭代器一次遍历我的列表中的一个项目。也就是迭代器中的next()方法不断被调用。接下来))将方法的返回值赋给ele,执行循环体语句。如果迭代器中所有元素都循环,next))方法会抛出StopIteration异常,意味着循环结束。
实际上,Python在执行循环时会在for循环中显式执行这两个3354,或者执行一个包含隐式循环的操作,比如otherlist.extend(mylist)。其中列出了其他列表。
因此,Python的iterable包括以下内容:
Python中可以使用for.in. loop的对象:list,dict,string,files。
实现用户定义的iter()方法的类实例。
发电机。
注意Python的for循环并不关心处理的是哪一个。如果处理是一个迭代器,可以通过next()方法一次调用一个元素,那么for循环可以正常工作。例如,使用For循环访问list的元素、dict的键、文件的行等。一个接一个。
建设者
其实生成器的功能和迭代器完全一样,只是生成器和迭代器的区别在于,生成器中的元素只能循环一次。这是因为生成器不会将所有元素都存储在内存中,而是动态生成下一个周期的元素。
这是一个迭代器。
mylist=[x*xforxinrange(3]) ]
对于我列表中的ele:打印(ele)。
0
一个
四
#这是发电机
mylist=(x*xforxinrange(3))))))))))))))).
对于我列表中的ele:打印(ele)。
0
一个
四
如您所见,只需将[]更改为()即可获得生成器。与迭代器不同,对于生成器,for ele in只能调用一次。
我的列表.因为生成器会先计算0,然后删除这部分;再算1,然后删除这部分,以此类推。也就是说,生成器不会将之前循环过的任何元素的值保存在内存中。
产量
yield关键字的使用类似于return,但区别在于yield关键字使函数返回一个生成器对象。请看下面的示例代码。
def createGenerator():
产量1
产量2
产量3
myGenerator=createGenerator()
打印(我的生成器)#(1)
对于myGenerator中的ele:
打印(ele) #(2)
print(myGenerator.next())
上述代码的三个输出结果是:
#(1)
一个
2
三
#(2)
回溯(最近一次呼叫):
文件“”中的第12行
停止迭代
#(3)
从输出结果我们可以看到yield关键字返回一个生成器,这个生成器只能循环一次。
当调用createGenerator()时,实际上它不会在yield语句中返回任何值。这个函数返回的实际上是一个生成器对象。其实功能并没有退出,只是处于暂停状态。当我们使用for循环遍历生成器时,函数将从挂起状态恢复,并继续执行最后执行的yield语句后面的代码。在createGenerator()中,也就是yield语句的下一行,然后将yield中的值返回给for循环。这个过程会一直持续下去,直到最后函数退出(函数退出,或者生成器为空,表示函数连续运行但是找不到yield语句。这可能是因为函数已经执行到底,也可能是因为我们的函数中包含的if/else条件无法持续满足)。此时,生成器抛出StopIteration异常,for循环结束。注意,当for循环第一次调用生成器时,函数将从头执行到第一个yield,并返回语句中的值。
相反,如果我们将createGenerator()中的yield替换为return,那么只会执行函数中的第一行,函数在返回1时结束。
在某种程度上,生成器的功能类似于适配器的功能。一方面,它的next()方法使for循环能够逐个获取下一个值。另一方面,它执行函数,直到获得下一个值,然后将函数重置为挂起状态。
为什么要用发电机?
通常,我们可以编写不使用生成器但实现完全相同逻辑的代码。一种方法是使用前面的list方法替换yield关键字。但是这种方法并不总是有效的。例如,当我们有一个无限循环时;而且如果列表很大,这种方法的内存利用效率很低。
另一种方法是实现另一个iterable类,并通过使用该类中的实例成员来记录状态。利用该类中实现的next()方法(Python3中为__next()__)实现逐循环操作。根据逻辑设计的需要,next()中的代码块可能非常复杂,容易出现bug。在这种情况下,使用发电机也可以提供一个干净的解决方案。
控制发电机元件的消耗
class Bank(): #让我们创建一个银行,建造自动取款机
.危机=错误
.定义创建_自动柜员机(自身):
.而不是自我危机:
.收益 100美元
当一切正常时,自动取款机会给你你想要的钱
corner _ street _ ATM=HSBC . create _ ATM()
print(corner_street_atm.next())
$100
print(corner_street_atm.next())
$100
print([corner _ street _ ATM . next()for cash in range(5)])
[$100, $100, $100, $100, $100]
hsbc.crisis=True #危机来了,没钱了!
print(corner_street_atm.next())
wall _ street _ ATM=HSBC . create _ ATM()#甚至对新的自动取款机也是如此
print(华尔街自动柜员机. next())
问题是,即使在危机过后,自动取款机仍然是空的
print(corner_street_atm.next())
brand _ new _ ATM=HSBC . create _ ATM()#建立一个新的,以恢复业务
对于全新自动柜员机中的现金:
.打印现金
$100
$100
$100
$100
$100
$100
$100
$100
$100
.
当需要控制资源的获取时,这种方法可能是有用的。
郑重声明:本文由网友发布,不代表盛行IT的观点,版权归原作者所有,仅为传播更多信息之目的,如有侵权请联系,我们将第一时间修改或删除,多谢。