生成器与简写
1、什么是生成器
在函数内但凡出现yield关键字,再调用函数就不会执行函数体代码,会返回一个值,该值称之为生成器
生成器本身也是迭代器
2、为什么要有生成器?
生成器是一种自定义迭代器的方式
3、如何使用?
def func():
print('first1')
print('first2')
print('first3')
yield 1 #暂停
print('second1')
print('second2')
print('second3')
yield 2 #暂停
print('third')
yield 3 #暂停
print('fourth')
g=func()#第一次调用不会执行,会返回一个值,该值是生成器generator
print(g)
print(g.__iter__().__iter__())#而通过iter进行转为迭代器可以发现g本身就是迭代器表明迭代器就是生成器
res1=next(g)
print(res1) #使用next会自上而下读取内容直到第一个yield暂停读取,并且返回yield后面跟的值 "1",如果不print就无法显示yie后面的值
res2=next(g)
print(res2)#第二次使用next会从第一次yield暂停的地方开始继续往下读取直到遇到下一个yoeld暂停
res3=next(g)
print(res3)
res4=next(g)
print(res4)#res4的时候虽然下面的内容还会读取,但是后面已经没有yield所以会跟迭代器一样读取完之后报错
for item in g:#跟迭代器一样,先g=iter(g) 虽然已经是迭代器对象,但是还会进行一步迭代器对象转换,
# 然后执行next(g)将值给item 变为item=next(g)
print(item) #for循环有自动捕捉异常功能,所以循环完之后不会报错
for item in range(1,10):#range(1,10)=iter(range(1,10)),item=next(range(1,10))
print(item)
# def my_range(start,stop,step=1):#开始值,结束值,步长开始值
# while start < stop: #循环开始值要小于结束值,因为顾头不顾尾
# yield start #开始值每一次循环到yield,就会暂停,然后进入下一个循环每次遇到yield都会暂停
# start+=step #步长默认是1,调整步长设置
# f = my_range(1,7,2)#res2=next(g)
print(res2)#第二次使用next会从第一次yield暂停的地方开始继续往下读取直到遇到下一个yoeld暂停
res3=next(g)
print(res3)
res4=next(g)
print(res4)#res4的时候虽然下面的内容还会读取,但是后面已经没有yield所以会跟迭代器一样读取完之后报错
for item in g:#跟迭代器一样,先g=iter(g) 虽然已经是迭代器对象,但是还会进行一步迭代器对象转换,
# 然后执行next(g)将值给item 变为item=next(g)
print(item) #for循环有自动捕捉异常功能,所以循环完之后不会报错
for item in range(1,10):#range(1,10)=iter(range(1,10)),item=next(range(1,10))
print(item)
# def my_range(start,stop,step=1):#开始值,结束值,步长开始值
# while start < stop: #循环开始值要小于结束值,因为顾头不顾尾
# yield start #开始值每一次循环到yield,就会暂停,然后进入下一个循环每次遇到yield都会暂停
# start+=step #步长默认是1,调整步长设置
# f = my_range(1,7,2)#因为有yield所以第一次就调用不运行,而返回一个生成器
# print(next(f))
# print(next(f))
# print(next(f))
# print(next(f))#运行一次就显示第一个yield暂停位置,直到最后一次取值结束后报错
# for i in my_range(1,7,2):
# print(i)
总结yield的功能:
1、提供一种自定义迭代器的方式
2、yield可以暂停住函数,返回值
yield VS return
相同点:都是用在函数内,都可以返回值,没有类型限制,没有个数限制
不同点:return只能返回一个值,能有多个return但是遇到其中一个就结束,yield可以返回多个值
# 了解知识
# yield 值
# x=yield
# x= yield 值
def dog(name):
food_list=[]
print('狗哥 %s 准备开吃' %name)
while True:
food=yield food_list#暂停 food=yield='一桶泔水'
print('狗哥[%s]吃了<%s>' %(name,food))
food_list.append(food)
alex_dog=dog('alex')
res1=next(alex_dog) # 初始化,即让狗准备好
print(res1)
# next(alex_dog) # 等同于alex_dog.send(None)
#
# next(alex_dog)
res2=alex_dog.send(('咖啡伴侣'))
print(res2)
res3=alex_dog.send('巧克力')
print(res3)
三元表达式
x=10
y=20
def max2(x,y):
if x > y:
return x
else:
return y
#简化
res = x if x>y else y #条件成立时x返回值,中间条件,条件不成立时值返回就为y
print(res)#专门针对if的用法
列表生成式
l=[i for i in range(1,10)]
print(l)
# names=["kk","yy","ff","xx"]
# names = [name+"Y" for name in names if name != "yy"]#for左侧是对循环时候所额外加的条件
# print(names) #一般就套用一次,多了反而不简洁,本末倒置
结果就为names=["kkY","ffY","xxY"]
字典生成式
keys=["name","age","sex"]
values=["egon",18,"male"]
res=zip(keys,values)
print(list(res)) #将两个列表内的值按照最少值的列表互相两个两个搭配在元组内
d={}
for k,v in zip(keys,values):
d[k]=v
print(d)
# d={k:v for k,v in zip(keys,values)}#先将keys与values互相搭配转为元组,接着通过左侧条件k:v形成字典
# print(d)
# zip() #拉链函数,会将内容配对后成为元组
info={'name': 'egon', 'age': 18, 'sex': 'male'}
keys=info.keys()#将key从字典内取出
print(keys)#产生的是没有值,只有调用才有值
values=info.values()#将values从字典内取出
print(values)
#如果将列表在字典内转化的时候,for左边就只有一个值,那么产生的是元组而非字典
# 生成器表达式
# g=(i for i in range(10))
# print(g)
#
# print(next(g))
# print(next(g))
# with open("db.txt","r") as f:
# d=(len(line) for line in f)
# print(max(d))
#print(max(d))#报错,因为在元组内,是生成器的表达式,for循环只有在文件打开的时候才能print找到所需要的,在文件外的情况下,就是文件关闭无法获取到
# with open("db.txt","r") as f:
# d=[len(line) for line in f]
# print(max(d))
#print(max(d))#可以获取到,因为列表内是一次性将全部内容循环出来,所以不论在什么地方都可以获得