python中generator是什么类型,Python global用法
在介绍yield之前,我们必须先解释一下Python的迭代器(iterator)和生成器(generator)。
I迭代器(迭代器)。
在Python中,可以对任何类型的Python使用for循环,包括列表和祖先。实际上,for循环可以用于可重复的对象。这是迭代器。
迭代器是实现迭代器协议的对象。在Python的迭代器协议中,使用next方法的对象输入下一个结果,并在一系列结果的结尾导致StopIteration。所有这些对象都可以用for循环或其他遍历工具在Python中重复。在迭代工具中,每次迭代都会调用next方法,以确定捕获StopIteration异常的时间和结束时间。
使用迭代器有一个明显的好处,就是一次只从一个对象读取一个数据不会增加内存开销。
例如,要逐行读取文件的内容,可以使用readlines()方法,并编写如下代码:
forlineinopen(test . txt . read lines)):
打字线
这是可行的,但不是最好的方法。因为他实际上是一次性将文件加载到内存中并逐行打印。如果文件很大,这种方法的内存开销会很高。
使用file的迭代器,我们可以写如下。
forlineinopen(test . txt)):#使用文件迭代器
打字线
这是最简单快捷的写作方法。它每次都使用迭代器读取下一行,而不是显式读取文件。
二。生成器(构造器))
生成器与Python中迭代器协议的概念相关联。简单来说,包含yield语句的函数是专门编译到生成器中的。调用该函数时,将返回支持迭代器接口的生成器对象。函数可能包含return语句,但它的作用是yield用来生成值。
与普通函数不同,它生成值并退出。生成器生成值后会自动挂起,挂起执行和状态。变量在本地保存状态信息,并在函数恢复时重新启用。
定义(n):forIinrange(n):产量i **2。
锻造(5):打印I,:。
0 : 1 : 4 : 9 : 16 :
要了解他是如何工作的,请尝试下一种方法:
t=g(5)).
t.next())
0
t.next())
一个
t.next())
四
t.next())
九
t.next())
16
t.next())
跟踪(mostrecentcalllast):
文件中的第1行
停止解释
执行next五次后,生成器抛出StopIteration异常,迭代结束。
我们来看收益率的例子。用生成器生成斐波那契数列。
deffab(最大) :
a,b=0,1
而最大:
产生
a,b=b,a b
forIinfab(20):打印I,,。
0、1、1、2、3、5、8、13、
看完这里就能理解发电机的抽象概念了~ ~。
三。补充
yield关键字用于定义生成器。它的具体作用是用它作为返回,从一个函数返回一个值,但不同的是,用yield返回后,可以从用yield返回的最后一个位置继续执行函数。即yield会返回一个函数,将返回值传递给调用者,然后“瞬移”回来,继续运行函数,直到yield语句再次返回新值。
使用yield返回时,调用者实际上获得的是迭代器对象。迭代器的值就是返回值。另外,当迭代器的next))方法被调用时,函数会继续还原yield语句的执行环境,直到遇到下一个yield。如果遇到yield,它将抛出一个异常来指示迭代的结束。
请看下面的例子:
def test _ yield(:…yield 1…yield 2…yield)1,2 ) a=test_yie
LD()a . next()1a . next()2a . next()(1,2) a.next()Traceback(最近一次调用last): File ,第1行,in?停止迭代
1.包含产量的函数
如果你看到一个函数包含yield,说明这个函数已经是一个生成器了,它的执行会和其他普通函数有很大不同。例如,下面的简单函数:
defh():
打印“勇敢”
产量5
h()
可以看到,调用h()后,print语句并没有执行!这就是屈服。那么,如何执行print语句呢?这是后面要讨论的问题。通过后面的讨论和学习,我们会了解yield的工作原理。
2.屈服是一种表达
在Python2.5之前,Python yield是一个语句,而现在在2.5中,yield是一个表达式,比如:
m=产量5
表达式的返回值(yield 5)会赋给M,所以认为m=5是错误的。那么如何得到(收益率5)的返回值呢?您需要使用稍后介绍的send(msg)方法。
3.通过下面的()语句看原理
现在,让我们来揭示yield是如何工作的。我们知道上面我们的h()在被调用后并没有被执行,因为它有一个yield表达式。因此,我们让它通过next()语句执行。next()语句将继续执行生成器,直到下一个yield表达式。例如:
defh():
打印“汶川”
产量5
打印战斗!
c=h()
下一个
调用后,h()开始执行,直到遇到yield 5,所以输出结果是:
汶川
当我们再次调用c.next()时,我们将继续执行,直到找到下一个yield表达式。因为它背后没有Python屈服,所以会抛出一个异常:
汶川
打架!
回溯(mostrecentcalllast):
文件/home/evergreen/Codes/yildd . py ,第11行,在
c .下一个()
停止迭代
4.发送(消息)和下一步()
了解了next()如何让包含yield的函数执行之后,我们再来看另一个非常重要的函数,send(msg)。其实next()和send()在某种意义上有类似的功能。区别在于send()可以传入yield表达式的值,而next()不能传入具体的值,只能传一个。所以我们可以看到c.next()和c.send(None)的功能是一样的。看看这个例子:
defh():
打印汶川,
m=yield5 #战斗!
printm
d=产量12
打印“我们在一起”!
c=h()
C.next()#等效于c.send(None)
c . send(‘战斗!’)#(yield5)表情给出的是‘打架!’输出结果是:
文传格斗!
需要提醒的是,第一次调用时,请使用next()语句或send(None)。不能使用send发送None以外的值,否则会得到错误,因为没有Python yield语句接收这个值。
5.send (msg)和next()的返回值
Send(msg)和next()有返回值。它们的返回值是特殊的,它们返回下一个yield表达式的参数。如收益率为5,则返回5。你在这里学到了什么吗?在本文的第一个例子中,在list中遍历生成器实际上调用了一个list。每次都是Next(),以及list的返回值。每次的Next()都是yield的参数,也就是我们开始认为的东西被推了进去。让我们继续上面的例子:
defh():
打印汶川,
m=yield5 #战斗!
printm
d=产量12
打印“我们在一起”!
c=h()
M=c.next()#m获取yield5的参数值5。
d=c.send(战斗!)#d获得yield12的参数值12。
打印我们永远不会忘记,m, ,d输出结果:
文传格斗!
我们永远不会忘记5.12日
6.throw()和close()中断生成器
中断发电机是一种非常灵活的技术。您可以通过抛出GeneratorExit异常来终止生成器。Close()方法的功能是一样的,其实在内部它调用throw(GeneratorExit)。让我们看看:
defclose(自身):
尝试:
self.throw(GeneratorExit)
except(GeneratorExit,StopIteration):
及格
否则:
raiseRuntimeError( generatoringoredgerenatorexit )
# Otherexceptionsarenotcaught
因此,当我们调用close()方法,然后调用next()或send(msg)时,将会引发一个异常:
回溯(mostrecentcalllast):
文件/home/evergreen/Codes/yildd . py ,第14行,在
d=c.send(战斗!)#d获得yield12的参数值12。
停止迭代
郑重声明:本文由网友发布,不代表盛行IT的观点,版权归原作者所有,仅为传播更多信息之目的,如有侵权请联系,我们将第一时间修改或删除,多谢。