python生成器


生成器

生成器对象

'''
生成器其实就是自定义迭代器

'''

# 在定义阶段其实就是定义一个普通函数
def my_ge():
    print('one')
    yield 123,123,333
    print
    yield 444,222,444
    
'''
当函数体内含有yield关键字 那么在第一次调用函数的时候 
并不会执行函数体代码 而是将函数变成了生成器(迭代器)
'''
调用函数:不执行函数体代码 而是转换为生成器(迭代器)

res = my_ge()
ret = res.__next__()  # 每执行一个__next__代码往下运行到yield停止 返回后面的数据
print(ret)
ret = res.__next__()  # 再次执行__next__接着上次停止的地方继续往后 遇到yield在停止
print(ret)

使用生成器自定义range功能

def range2(start, stop = None, step = 1):  
    if not stop:
        stop = start
        start = 0   
    while start < stop:
        yield start    # 每次都会在这里停止 执行下一个__next__()方法才继续往后走
        start += step
res = range2(10)  # 将range2变成生成器
for i in res
	print(i)
        
res = range2(1,10)
for i in res
	print(i)
    
res = range2(1,10,2)
for i in res
print(i)

#  这样和内置的range方法基本上用法就差不多了

yield传值

def eat(name):
    print('%s 准备干饭!!!'%name)
    while True:
        food = yield
        print('%s 正在吃 %s' % (name, food))
res = eat('jason')  # 并不会执行代码 而是转换成生成器
res.__next__()  # 运行到yield停止
res.send('xxxx')  #  可直接传值
res.send('好吃的')  

yield与return对比

yield
	1.可以返回值(支持多个并且组织成元组的形式)
    2.函数代码体遇到yield不会结束而是'暂停'
    3.yield可以将函数变成生成器 并且支持外界传值
return
	1.同样可以返回值(支持多个并且组织成元组的形式)
    2.函数体代码遇到return直接结束

生成器表达式

l = [11,22,33,44,55,66,77,88,]
res = [i+1 for i in l]  #列表生成式
print(res)

res1 = (i+1 for i in l if i!=44)

'''
生成器表达式内部的代码只有在迭代取值的之后在会执行
'''

生成器练习题


# 求和
def add(n, i):
    return n + i
# 调用之前是函数 调用之后是生成器
def test():
    for i in range(4):
        yield i
g = test()  # 初始化生成器对象
for n in [1, 10]:
    g = (add(n, i) for i in g)
    """
    第一次for循环
        g = (add(n, i) for i in g)
    第二次for循环
        g = (add(10, i) for i in (add(10, i) for i in g))
    """
res = list(g)
print(res)

#  输出为: res=[20,21,22,23]