一、生成器与yield
若函数体包含yield关键字,再调用函数,并不会执行函数体代码,得到的返回值即生成器对象。
def my_range(start, stop, step=1):
print("start...")
while start < stop:
yield start
start+=step
print("end...")
g=my_range(0,3)
print(g) # <generator object my_range at 0x00000000024A60C8>
生成器内置有__iter__和__next__方法,所以生成器本身就是一个迭代器
print(g.__next__)
# <method-wrapper '__next__' of generator object at 0x00000000022860C8>
print(g.__iter__)
# <method-wrapper '__iter__' of generator object at 0x00000000022860C8>
因而可以用next(生成器)出发生成器所对应函数的执行
print(next(g))
# start...
# 0
print(next(g))
# 1
print(next(g))
# 2
print(next(g))
#end...
print(next(g))
Traceback (most recent call last):
File "C:/Users/Administrator/PycharmProjects/Test/180days/函数/test.py", line 213, in <module>
print(next(g))
StopIteration
既然生成器对象属于迭代器,那么必然可以使用for循环迭代,如下:
for i in g:
print(i)
start...
0
1
2
end...
有了yield关键字,我们就有了一种自定义迭代器的实现方式。yield可以用于返回值,但不同于return,函数一旦遇到return就结束了,而yield可以保存函数的运行状态挂起来,用来返回多次值。
二、yield表达式应用
在函数内可以采用表达式形式的yield
def eater():
print("Ready to eat!")
while True:
food = yield
print("get the food %s,ready to eat"%food)
e = eater() # 得到生成器对象
print(e) # <generator object eater at 0x0000000001D97B48>
next(e) # 初始化,让函数挂起在food = yield, 等待调用g.send( )方法为其传值
# Ready to eat!
e.send("鸡腿")
# get the food 鸡腿,ready to eat
针对表达式形式的yield,生成器对象必须事先被初始化一次,让函数挂起在food = yield的位置,等待g.send()方法为函数体传值,g.send(None)等同于next(g).
可以编写装饰器来完成为所有表达式形式yield对应生成器的初始化操作,如下:
def init(func):
def wrapper(*args,**kwargs):
e = func(*args,**kwargs)
next(e) # 初始化
return e
return wrapper
@init
def eater():
print("Ready to eat!")
while True:
food = yield
print("get the food %s,ready to eat"%food)
表达式形式的yield也可以用于多次返回值,即 变量名 = yield 值的形式,如下:
def eater():
print("ready to eat")
food_list = []
while True:
food = yield
food_list.append(food)
print(food_list)
e = eater()
next(e)
e.send("蒸羊羔") # ['蒸羊羔']
e.send("蒸熊掌") # ['蒸羊羔', '蒸熊掌']
e.send("蒸鹿尾儿") # ['蒸羊羔', '蒸熊掌', '蒸鹿尾儿']
三、三元表达式、列表生成式、生成器表达式
3.1 三元表达式
三元表达式是python为我们提供的一种简化代码的解决方案,语法如下:
res = 条件成立时返回值 if 条件 else 条件不成立时返回的值
举例如下:
def max(x, y):
if x > y:
return x
elif x < y:
return y
三元表达式:
x = 0
y = 1
res = x if x>y else y
3.2 列表生长式
列表生成式是python为我们提供的一种简化代码的解决方案,用来快速生长列表。
例子如下:
egg_list = []
for i in range(10):
egg_list.append("鸡蛋%s"%i)
列表生成式:
egg_list = ["鸡蛋%s"%i for i in range(9)]
3.1 生成器表达式
创建一个生成器对象有两种方式,一种是调用yield关键字的函数,另一种就是生成器表达式,与列表生成式的格式相同,只是把[ ]换成( ) ,即:
(expression for item in iterable if condition)
列表生成器返回值是一个列表
生成器表达式返回的是一个生成器对象,其优点是节省内存(一次只产生一个值在内存中)
如果要读取一个大文件,应该基于生成器表达式的方式完成:
with open("db.txt","rb") as f:
nums = (len(line) for line in f)
total_size = sum(nums) # 依次执行next(nums),然后累加到一起得到结果。