Effective Python书中,第16条建议:考虑用生成器来改写直接返回列表的函数
通常情况下,如果我们自定义一个函数要返回一个列表,可能会把每个值append加入到列表,最终返回该列表。
例如,查出字符串中每个单词首字母所处的位置:
#通常做法可能这样
def index_words(pstr):
result=[]
if pstr:
result.append(0)
for index,letter in enumerate(pstr):
if letter==" ":
result.append(index+1)
return result
#引入生成器这样,关键词yield
def index_words_iter(pstr):
if pstr:
yield 0
for index,letter in enumerate(pstr):
if letter==" ":
yield index+1
对比以上可知,使用生成器:1.代码简洁;2.内存开销更小
生成器与迭代器概念
- 生成器
在Python中包含yield语句的函数会被特地编译成生成器(generator)。当函数被调用时,他们仅返回一个iterable对象,这个对象支持迭代器接口。函数功能类似return语句,但它的作用是用来yield产生值的。不像一般的函数会生成值后退出,生成器函数在生成值后会自动挂起并暂停他们的执行和状态,他的本地变量将保存状态信息,这些信息在函数恢复时将再度有效 - 迭代器
迭代器是一个实现了迭代器协议的对象,Python中的迭代器协议就是有next方法的对象会前进到下一结果,而在一系列结果的末尾是,则会引发StopIteration。任何这类的对象在Python中都可以用for循环或其他遍历工具迭代,迭代工具内部会在每次迭代时调用next方法,并且捕捉StopIteration异常来确定何时离开。从另一个方面也说明了迭代器存在有效性,同一个迭代对象不能反复被利用,例如:
i=index_words_iter("hi wo id") #得到一个迭代对象,不会真正执行index_words_iter函数的内部代码
for l in i: #执行函数内部代码
print(l) #打印出迭代对象的每个值
print(list(i)) #结果为空列表