Python之yield
1.问题描述
在之前的学习中,对于返回需要进行迭代序列的函数,一般都是通过列表进行返回的。比如想要生成一个1
2
到x
2
的序列时会选择:
def square(max_number):
L = []
count = 1
while count <= max_number:
L.append(count ** 2)
count += 1
return L
print(square(5))
另一个例子出现在读文件时,这样的方式会将文件的每行加入到一个列表中,最后进行返回,可以用于迭代。
def read(file_path):
L = []
with open(file_path,"r") as f:
line = f.readline()
while line:
L.append(line)
line = f.readline()
return L
print(read("test"))
但这样的方式会占用不可知大小的内存,因为返回列表这种方式所消耗的内存资源无疑是受到了列表长度的影响。列表短的时候占用内存少,列表长的时候占用内存会很多。
2.yield版解决方案
先直接放代码,解释在后面
1
2
到x
2
的yield方案
def square(max_number):
count = 1
while count <= max_number:
yield count ** 2
count += 1
for each in square(5):
print(each)
读文件的yield方案
def read(file_path):
with open(file_path,"r") as f:
line = f.readline()
while line:
yield line
line = f.readline()
for each in read("test"):
print(each)
看完这两段代码我第一感觉是:没看懂。这两个函数没有return语句,还能用在for循环中?这些疑惑都需要了解generator函数才能解决。
3.yield与generator
在有关yield的教程中都会多次提到generator,在此我简单列了我对generator函数的理解:
generator函数是一种可以多次返回的函数,它们使用yield进行返回
generator函数执行到yield进行返回后不会运行结束,而是进入类似中断的状态,等待继续运行的信号(所谓的next()方法)
for循环每次循环都会调用generator函数的next方法,使其继续运行
以1
2
到x
2
的yield版代码为例,整个square(5)的执行过程应该是这样:
1.for each in square(5)第一次执行,for循环让square(5)开始执行
2.square(5)顺序执行到yield,返回1,并停止运行
3.each被赋值1,print(each)打印1
4.for each in square(5)第二次执行,for循环让square(5)开始执行
5.square(5)继续执行到yield,返回4,并停止运行
……
n.square(5)继续执行,但不再执行到yield,因此不会再返回数据(for循环可以自动处理这个问题),for循环停止
4.总结
yield的好处体现在代码可读性和资源占用上,但现在我还不清楚除了for循环中还有哪儿能使用yield,对generator类型函数的了解也不是很多,有机会的话还需要更深入的学习