如果函数要返回一系列结果,那么最简单的做法就是把这些结果都放在一个列表里返回。例如,我们要查出字符串中每个单词的首字母的位置。下面这段代码是可能的一种实现:
def index_words(text):
result = []
if text:
result.append(0)
for index,letter in enumerate(text):
if letter == ' ':
result.append(index+1)
return result
address = 'Four score and seven years ago...'
result = index_words(address)
print(result[:3])
输出结果:
[0, 5, 11]
index_words函数有两个问题:一是写得有点拥挤。每次找到新的结果,都要使用append方法。二是函数开始和结束各有一段代码来创建及返回result列表。
这个函数如果用生成器(generator)来写会更好。生成器使用yield表达式。关于yield的用法见我的另一篇博客:
https://blog.csdn.net/weixin_44981444/article/details/108618076
改写后的代码如下:
def index_words_iter(text):
if text:
yield 0
for index,letter in enumerate(text):
if letter == ' ':
yield index +1
address = 'Four score and seven years ago...'
#result = index_words(address)
result = list(index_words_iter(address))
print(result[:3])
用yield的好处在于处理的数据量大时,能防止内存占用过大。
如果处理文件,可以用下面这段:
def index_file(handle):
offset = 0
for line in handle:
if line:
yield offset
for letter in line:
offset += 1
if letter == ' ':
yield offset
with open('address.txt','r',encoding='utf-8') as f:
it = index_file(f)
results = islice(it,0,3)
print(list(results))
定义这种函数时,唯一要注意的是,迭代器是有状态的,只能用一次。
要点:
- 使用生成器比把收集到的结果放入列表里返回给调用者更加清晰。
- 由生成器函数所返回的个迭代器,可以把生成器函数体中,传给yield表达式的那些修理,逐次产生出来。
- 无论输入量有多大,生成器都能产生一系列输出,因为这些输入量和输出量,都不会影响它在执行时所耗的内存。