生成器

一 生成器与yield

  若函数体包含yield关键字,再调用函数,并不会执行函数体代码,得到的返回值即生成器对象

def func():
    print('第一次')
    yield 1
    print('第二次')
    yield 2
    print('第三次')
    yield 3
    print('第四次')    
g=func()
print(g)
#生成器就是迭代器
g.__iter__()
g.__next__()

# 会触发函数体代码的运行,然后遇到yield停下来,将yield后的值
# 当做本次调用的结果返回
res=g.__next__()
print(res)

# 应用案列
def my_range(start,stop,step=1):
    # print('start...')
    while start < stop:
        yield start
        start+=step
    # print('end....')

for n in my_range(1,7,2):
    print(n)

  总结yield:有了yield关键字,我们就有了一种自定义迭代器的实现方式。yield可以用于返回值,但不同于return,函数一旦遇到return就结束了,而yield可以保存函数的运行状态挂起函数,用来返回多次值

二 yield表达式应用

  在函数内可以采用表达式形式的yield

def dog(name):
    print('%s准备吃东西啦'%name)
    while True:
        # x拿到的是yield接收到的值
        x = yield
        print('%s吃了 %s' %(name,x))

  可以拿到函数的生成器对象持续为函数体send值,如下

g=dog('alex')
g.send(None) # 等同于next(g)

g.send('肉包子')
g.send('一同泔水')
g.close()
g.send('1111') # 关闭之后无法传值

  针对表达式形式的yield,生成器对象必须事先被初始化一次,让函数挂起在food=yield的位置,等待调用g.send()方法为函数体传值,g.send(None)等同于next(g)。

  表达式形式的yield也可以用于返回多次值,即变量名=yield 值的形式,如下

def dog(name):
    food_list=[]
    print('道哥%s准备吃东西啦...' %name)
    while True:
        # x拿到的是yield接收到的值
        x = yield food_list # x = '肉包子'
        print('道哥%s吃了 %s' %(name,x))
        food_list.append(x) # ['一根骨头','肉包子']
g=dog('alex')
res=g.send(None)  # next(g)
print(res)

res=g.send('一根骨头')
print(res)

res=g.send('肉包子')
print(res)

三 三元表达式、列表生成式、生成器表达式

  3.1三元表达式

  三元表达式是python为我们提供的一种简化代码的解决方案,语法如下

res = 条件成立时返回的值 if 条件 else 条件不成立时返回的值

  针对下述场景

def func(x,y):
    if x > y:
        return x
    else:
        return y
res=func(1,2)

  用三元表达式可以一行解决

x=1
y=2
res = x if x > y else y # 三元表达式

  

  3.2列表生成式

    列表生成式是python为我们提供的一种简化代码的解决方案,用来快速生成列表

     针对如下场景:

l = ['alex_dsb', 'lxx_dsb', 'wxx_dsb', "xxq_dsb", 'egon']
new_l=[]
for name in l:
    if name.endswith('dsb'):
        new_l.append(name)

    用列表生成式可以一行解决

new_l=[name for name in l if name.endswith('dsb')]

  3.3生成器扩展 

    字典生成式

keys=['name','age','gender']
dic={key:None for key in keys}
print(dic)

items=[('name','egon'),('age',18),('gender','male')]
res={k:v for k,v in items if k != 'gender'}
print(res)

    集合生成式

keys=['name','age','gender']
set1={key for key in keys}
print(set1,type(set1))

  3.4生成器表达式

  创建一个生成器对象有两种方式,一种是调用带yield关键字的函数,另一种就是生成器表达式,与列表生成式的语法格式相同,只需要将[]换成()

(expression for item in iterable if condition)

  对比列表生成式返回的是一个列表,生成器表达式返回的是一个生成器对象

g=(i for i in range(10) if i > 3)
# !!!!!!!!!!!强调!!!!!!!!!!!!!!!
# 此刻g内部一个值也没有
print(g,type(g))
print(g)
print(next(g))#调用一次next才会有一个值
print(next(g))

  如果我们要读取一个大文件的字节数,应该基于生成器表达式的方式完成

with open('笔记.txt', mode='rt', encoding='utf-8') as f:
    res = sum(len(line) for line in f)
    print(res)
原文地址:https://www.cnblogs.com/bk134/p/12560422.html