Python生成式,python生成器详解
Python generator和Python decorator几乎不相上下,在python世界中占据重要地位。如果说python decorator是为了让程序员悄悄扩展函数功能,那么python generator就是为了让你的代码更节省资源,更高效!讲真,python generator比python decorator更抽象更灵活,功能更强大,所以我只能大致说“python generator就像一把瑞士军刀,让你的代码更短(简洁),更简洁(强大)”。
让我们首先来看一段运行在python2环境中的代码:
#注意在python3.x中range和xrange已经合并,这段代码必须在py2下运行!对于范围(3)中的I:print(I)print(-)for I in xrange(3):print(I)print(-)lst 1=[X * X for X in range(3)]lst 2=(X * X for X in range(3))for I:print(I)print(-)for I in lst 2:print(I)打印结果如下:
012 - 014.看完这段代码,你可能会说:python真麻烦。有range和xrange,[]和(),运行结果是一样的。这不是白费力气吗?
现在让我们稍微修改一下代码:
a=range(3)B=xrange(3)print(type(a))print(a[0],a[1])print(-)print(type(B))print(B[0],B[1])print(-)lst 1=[x * x for x in range(3)]lst 2=(x * x for x in range(3))print(type(lst 1))print(type(type(lst 2))。打印结果如下
Type list [0,1,2] (0,1)-type xrange xrange (3) (0,1)-type list type generator 这里需要解释一下:range()也就是说,[]返回一个列表list,()返回一个生成器。
*注意:Iterables是用[]派生的。生成器派生自()。*
可迭代对象(iterable) 与 迭代器(iterator)
Iterable iterable对象是实现__iter__()方法的对象。更确切地说,是容器。__iter__ iterator _ _()方法,该方法返回一个迭代器对象,因此可以从iterable对象中获取迭代器迭代器。在python中,迭代一般由for … in …来完成,只要是可迭代的对象,都可以迭代。
例如,在下面的遍历中
对于某物的价值,某物是一个可重复的对象。例如列表、字符串、文件。
对于iterable,我们要注意的是,它是一个可以一次返回一个成员的对象(iterable是一个能够一次返回一个成员的对象)。有些iterables在内存中存储所有的值,比如list,有些则没有,比如iterator,我们下面会讲到。
Iterator(迭代器)是实现__next__()方法的对象,不带参数,返回序列中的下一个元素;如果没有元素,将引发StopIteration异常。Python的迭代器也实现了_ _ iterator _ _()方法,所以迭代器也是可迭代的。
迭代器。next()是区别iterator和iterable的关键。它允许我们显式地获取一个元素。当调用next()方法时,实际上会生成两个操作:
更新迭代器状态,为下一次调用指向后一项;返回当前结果;两者之间的关系如下:
Iter(可迭代对象)生成迭代器。
S=abc #s是可迭代对象it=ITER(s)#它是I的迭代器:print(i)我们暂时不需要遍历这个迭代器,我们尝试调用next()方法。
s= ABC it=ITER(s)next(it) a s= ABC it=ITER(s)next(it) a next(it) b next(it) c next(it)trace back(最近一次调用last):modulestopitation中的File stdin ,第1行,除了最后一行抛出异常外,其他结果与for loop相同。也就是说,当iterator)X被for循环遍历时,X的next()方法会被循环调用,得到每次的值,直到iterator为空,返回的StopIteration作为循环结束的标志。For … in …将自动处理StopIteration异常,从而避免引发异常并中断程序。
当我们用for … in …对一个iterable对象进行iterate时,实际上是通过调用iterator()方法得到一个迭代器,假设这个迭代器叫做X,然后我们在一个循环中调用X的next()方法每次都得到值,直到迭代器为空,返回的StopIteration作为循环结束的标志。for … in …将自动处理StopIteration异常,从而避免
需要注意的是,迭代器是消耗性的,即每个值用完后就消失了。所以,你可以把上面的操作2理解为pop。遍历完迭代器,就变成了空容器,但不等于无。所以如果想重用迭代器,用list()方法保存其结果是个不错的选择。
代码如下:
从集合导入迭代,迭代器a=[1,2,3] #众所周知,list是一个可迭代的b=iterator (a) #通过iterator()方法,迭代器,iter获得,iterator()实际使用_ _ iterator _ _(),从此以后,我就不再多说isinstance (a,iterator) true isinstance (a,iterator) false isinstance (b,iterator) true #。可见itertor一定是可迭代的。但是iterable不一定是itertor # iterator是消耗性的。少用一次用一次。变量迭代器和迭代器将为空!C=list(b) c[1,2,3] d=list(b) d[]#空迭代器不等于无。如果b:打印(1).1如果b==无:打印(1).#再来感受下一个()e=迭代器。
只要Python函数的定义中有yield关键字,该函数就是生成器函数。当调用生成器函数时,将返回一个生成器对象。即生成器功能是一个生成器工厂。
函数返回一个值,而生成器函数生成一个值。不仅如此,函数返回值后退出,而且生成器可以产生多个值,生成器函数中可以出现多个yield。
生成器概念
如何生成发电机?有两种方法:
1.生成器函数:带有yield关键字的函数是生成器函数,其返回值是生成器。
2.生成器表达式:形式为(elem for elem in [1,2,3])的表达式称为生成器表达式,也可以生成生成器。
生成器表达式生成生成器:
Gen=(I for I in [2,3,4,5,6]) Gen生成器对象Gen EXPRAT0x 0000178d 648 D1 A8 for I in Gen:打印(一).23456我们调用next()方法,这也是可能的:
gen=( i for i in [2,3,4,5,6])next(gen)2 next(gen)3 next(gen)4 next(gen)5 next(gen)6 next(gen)trace back(最近一次调用last):文件 stdin ,第1行,在moduleStopIteration中。这和上面迭代器的使用是一样的!
实际上,生成器是一种迭代器,以更优雅的方式实现,可以像迭代器一样使用。当然,除了定义迭代器,还需要分别实现_ _ iterator _ _()方法和_ _ next_ _()方法,但生成器只需要yield关键字。
生成函数发生器
def gen123():产量1.产量2.产量3.gen123函数gen 123 at0x 00000178d 6614d 08 gen 123()生成器对象gen 123 at0x 00000178d 648 D1 A8 for I in gen 123():打印(一).123这里你也可以猜到,我们在调用next()方法的时候会抛出一个异常,效果是一样的:
def gen123():产量1.产量2.产量3.gen=gen 123()next(gen)1 next(gen)2 next(gen)3 next(gen)trace back(最近一次调用last) : file stdin ,line1,in modulation实际上,for循环每次隐藏时都会调用next()方法,并前进到函数中的下一个yield语句。
如何“生成”生成器
生成器的另一项黑科技是,生成器中的yield语句将挂起生成器函数的状态,并保留足够的信息,以便它可以从停止的地方继续执行。
让我们看看代码:
Genab (): #.打印(“开始”).产出 a #.打印(“继续”).产量 b #.打印(结束)#.对于genab()中的I:#.打印(-
Start - Acontinue - Bend定义生成器函数的方式与普通函数相同,只是使用了yield关键字。
当第一次在for循环(序列号)中隐式调用next()函数时,它将打印
开始,然后在第一个yield语句处停止,以生成值 a 。
当在for循环中第二次隐式调用next()函数时,它将打印
“继续”,然后在第二个yield语句处停止,以生成值“b”。
第三次调用next()函数时, end。然后到达函数定义体。
在结束时,生成器对象引发StopIteration异常。
迭代时,for机制的作用与g=iter(gen_AB())相同,用于get
生成器,然后每次迭代都调用next(g)。
循环打印以及next(g)返回的值。然而
在print函数输出结果之前,您不会看到这个输出。
“Start”是生成器函数定义体中打印(“start”)输出的结果。
生成器定义体中的yield A a 语句将生成值A,该值将提供给for-follow。
Ring,而A会赋给变量I,最终输出是A。
第二次调用next(g),继续迭代。生成器函数定义体中的代码包括
收益率“a”上升到收益率“b”。文本continue由生成器函数定义。
中第二个打印函数的输出。
yield B b 语句生成值B,提供给for循环,B赋给变量。
c,所以循环打印出B。
第三次调用next(it),继续迭代,前进到生成器函数的末尾。文本
结束。由生成器函数定义体中的第三个打印函数输出。到达生成
当函数定义了主体的结尾时,生成器对象抛出一个StopIteration异常。为
该机制捕捉异常,因此当循环终止时不会报告错误。
郑重声明:本文由网友发布,不代表盛行IT的观点,版权归原作者所有,仅为传播更多信息之目的,如有侵权请联系,我们将第一时间修改或删除,多谢。