Python3生成器

跟普通函数不同的是,生成器是一个返回迭代器的函数,只能用于迭代操作,更简单点理解生成器就是一个迭代器。

列表推导式用中括号,生成器表达式用小括号

>>>[i for i in range(5)]       #列表解析
>>>g = (i for i in range(5))   #小括号() 
#生成器表达式,不用yield的表达形式
>>> type(g)          #这是一个迭代对象
'generator'>
>>>print(next(g))    #next(g)相当于g.__next__()
0
>>>print(next(g))  
1  
>>>print(next(g))    #迭代到头是len(list(range(5)))
2     
#或者直接用sum迭代到头
>>> sum(g)
9
>>> print(next(g))  #迭代到头再迭代生产会报错
Traceback (most recent call last):
  File "", line 1, in 
    print(next(g))
StopIteration

在 Python 中,使用了 yield 的函数被称为生成器(generator)。在调用生成器运行的过程中,每次遇到 yield 时,函数会暂停,并保存当前所有的运行信息,返回yield的值在下一次执行 next()方法时,从当前位置继续运行
生成器函数和普通函数定义类似,不过要有标志性语句:yeild,返回生成器,通过next进行断电式运行。

>>> def gener():
    yield 3 
>>> g=gener();type(g)
<class 'generator'>
>>> next(g)
3
>>> next(g)
Traceback (most recent call last):
  File "", line 1, in <module>
    next(g)
StopIteration
>>> def gen_test():
    while True:
        yield 3
        print('once time')
>>> g=gen_test()   #生成器对象g
>>> type(g)
<class 'generator'>
>>> next(g) #生成器执行到yield暂停,并返回yield值
3
>>> next(g) #生成器从暂停处开始执行,到下一个yield执行完停止
once time
3
>>> next(g)
once time
3

下面例子对比上面例子,区别yield&print和yield&return连用的结果,形象化理解生成器的yield执行层级

>>> def gen_test1():
    while True:
        yield 3
        return "stop"   
>>> g1=gen_test1()
>>> type(g1)
<class 'generator'>
>>> next(g1)
3
>>> next(g1)    #从上一次yield停止处执行return
Traceback (most recent call last):
  File "", line 1, in <module>
    next(g1)
StopIteration: stop

生成器

生成器是一个特殊的程序,可以被用作控制循环的迭代行为。
生成器类似于返回值为数组的一个函数,这个函数可以接收参数,可以被调用,但是,不同于一般的函数会一次性返回包含了所有数值的数组,生成器一次只产生一个值,这样消耗的内粗数量大大减少,而且允许调用函数可以很快的开始处理前几个返回值。因此,生成器看起来像一个函数但是表现的却像一个迭代器。

python中的生成器,提供了两种基本的方式

生成器函数:也是用def来定义,利用关键字yield一次返回一个结果,阻塞,重新开始。
生成器表达式:返回一个对象,这个对象只有在需要的时候才产生结果。

生成器函数

为什么叫生成器函数?因为他随着时间的推移生成了一个数值队列。一般的函数在执行完毕之后会返回一个值然后退出,但是生成器函数会自动挂起,然后重新拾起继续执行,他会利用yield关键字关起函数,给调用者返回一个值,同时保留了当前的足够多的状态,可以使函数继续执行。生成器和迭代协议是密切相关的,可迭代的对象都有一个next()成员方法,这个方法要么返回迭代的下一项,要么引起异常结束迭代。为了支持迭代协议,拥有yield语句的函数被编译为生成器,这类函数被调用时返回一个生成器对象,返回的对象支持迭代接口,即成员方法next()继续从中断处执行执行。

def create_counter(n):
    print("create counter")
    while True:
        yield 'out',n
        print('increment n')
        n += 1

cnt = create_counter(2)
print(cnt)
#

print(next(cnt))
#create counter
#('out', 2)

print(next(cnt))
#increment n
#('out', 3)

print(next(cnt))
#increment n
#('out', 4)

在create_counter函数中出现了关键字yield,预示着这个函数每次只产生一个结果值,这个函数返回一个生成器(通过第一行输出可以看出来),用来产生连续的n值。在创造生成器实例的时候,只需要像普通函数一样调用就可以,但是这个调用却不会执行这个函数,这个可以通过输出看出来。next()函数将生成器对象作为自己的参数,在第一次调用的时候,执行了create_counter()函数到yield语句,返回产生的值2。重复调用next()函数,每次都会从上次被挂起的地方开始执行,直到再次遇到了yield关键字。

def cube(n):
    for i in range(n):
        yield i ** 3
#***在for循环中,会自动遵循迭代规则,每次调用next()函数***
for i in cube(5):
    print(i)
#0 1 8 27 64
###############################
def cubet(n):
    for i in range(n):
        yield i ** 3
cb=cubet(5)        
print(next(cb))
print(next(cb))
#0 1

你可能感兴趣的:(Python)