Python生成器函数

生成器

  生成器指的是生成器对象,可以由生成器表达式生成,也可以使用yield关键字编写一个生成器函数,调用这个函数得到一个生成器对象。

  生成器对象是一个可迭代对象,是一个迭代器

  生成器对象是延时计算,惰性求值的对象

m = (i for i in range(10))

type(m)m

(generator, <generator object <genexpr> at 0x000001AFE65720A0>)

生成器函数

  函数体中包含yield关键字的函数,就是生成器函数,调用后返回生成器对象

def g():
    for i in range(10):
        yield i 
f = g()
type(f),f
(generator, <generator object g at 0x000001AFE65721A8>)

可使用next(f)驱动

普通函数调用,函数会立即执行,直到执行结束,生成器函数调用,并不会立即执行函数体,而是返回一个生成器对象,需要使用next()内嵌函数来驱动这个生成器对象

生成器表达式和生成器函数都可以得到一个生成器对象,只不过生成器函数可以写的更加的复杂。

 

生成器函数的执行

def foo():
    print(1)
    yield 2 #暂停当前函数执行
    print(3)
    yield 4 
    print(5)
    return 6  #函数遇到return语句立即返回,后面的语句不执行
    yield 7

next(foo()) #每次运行都是生成新的对象

f = foo()

next(f)

 

在生成器函数中,可以使用多个yield,每执行一次yield后会暂停执行,把yield表达式的值返回

再次执行会到下一个yield语句又会暂停执行

return语句依然可以终止函数执行,但是return语句的返回值不能被获取到

return语句会导致当前函数返回无法继续进行,也无法获取到下一个值,抛出StopIteration

如果函数没有显式return语句,如果生成器函数执行到结尾,相当于return None,使用next()驱动一样会抛出StopIteration异常

 

生成器应用

无限循环

def counter():
    i = 0 
    while True:
        i += 1 
        yield i

c = counter()

x = 0 
for i in c:
    x += 1 
    if x > 10: 
        break 
    print(i)

 

计数器

def inc():
    def counter():
        i = 0
        while True:
            i += 1
            yield i 
    c = counter()
    return c 

g = inc()
next(g)

 

def inc():
    def counter():
        i = 0
        while True:
            i += 1
            yield i 
    c = counter()
    def inner():
        return next(c)  #用到了闭包
    return inner
foo = inc()
foo() #重复执行
#输出
1
2
3
.....

使用lambda匿名函数实现:

def inc():
    def counter():
        i = 0
        while True:
            i += 1
            yield i 
    c = counter()
    return lambda :next(c)

foo = inc()
foo() #重复执行
#输出
1
2
3
.....

使用生成器函数计算菲波那切数列:

def fib():
    x = 0
    y = 1
    while True:
        yield y
        x, y = y, x + y

foo = fib()
for x in range(5):
    print(next(foo))

 

def inc():
    def fib():
        x = 0 
        y = 1
        while True:
            yield y 
            x,y = y,x+y
    foo = fib()
    return lambda : next(foo)


g = inc()

for x in range(10):
    print(g())

 

 

重置功能的计数器:

send()方法:调用send方法,可以吧send的实参传给yield语句做结果,这个结果可以在等式右边被赋值给其他变量

send和next可以推动生成器函数启动并执行

 

 x = yield i 赋值语句,到右边就暂停,x拿到的是None,send驱动同时带一个值过来

def inc():
    def counter():
        i = 0
        while True:
            i += 1
            response = yield i 
            if response is not None:
                i = response
    c = counter()
    def inner(flag=False):
        if flag:
            return c.send(0)
        else:
            return next(c)
    return inner
    #lambda flag=False : c.send(0) if flag else next(c) #第二种写法
g = inc()
g()
g(flag=True)

 

yield from语法:

yield from就是一种语法糖

def foo():
    for i in range(10):
        yield i 

#####两个等价#######
def foo():
    yield from range(10)

 

  

posted @ 2020-04-17 13:16  Alrenn  阅读(332)  评论(0)    收藏  举报