在这种情况下使用生成器有什么好处?
我正在通过这个幻灯片学习Python的生成器:http://www.dabeaz.com/generators/Generators.pdf
里面有一个例子,可以这样描述:
你有一个叫做 log.txt
的日志文件,写一个程序来监视它的内容,如果有新行被添加到里面,就打印出来。有两种解决方案:
1. with generator:
import time
def follow(thefile):
while True:
line = thefile.readline()
if not line:
time.sleep(0.1)
continue
yield line
logfile = open("log.txt")
loglines = follow(logfile)
for line in loglines:
print line
2. Without generator:
import time
logfile = open("log.txt")
while True:
line = logfile.readline()
if not line:
time.sleep(0.1)
continue
print line
那么在这里使用生成器有什么好处呢?
5 个回答
生成器函数的定义方式和普通函数一样,不过当它需要生成一个值的时候,它使用的是“yield”这个关键词,而不是“return”。它的主要优点是可以让代码逐步产生一系列的值,而不是一次性计算出所有值并像列表那样返回给你。例如:
# A Python program to generate squares from 1
# to 100 using yield and therefore generator
# An infinite generator function that prints
# next square number. It starts with 1
def nextSquare():
i = 1;
# An Infinite loop to generate squares
while True:
yield i*i
i += 1 # Next execution resumes
# from this point
# Driver code to test above generator
# function
for num in nextSquare():
if num > 100:
break
print(num)
使用“return”会把一个指定的值返回给调用它的地方,而“yield”则可以产生一系列的值。当我们想要逐个处理一系列数据,但又不想把整个序列都存储在内存里时,就应该使用“yield”。
一个好处是你可以把生成器传递给其他函数,然后通过调用 .next()
来手动迭代。下面是你最初生成器示例的一个稍微修改过的版本:
import time
def follow(file_name):
with open(file_name, 'rb') as f:
for line in f:
if not line:
time.sleep(0.1)
continue
yield line
loglines = follow(logfile)
first_line = loglines.next()
second_line = loglines.next()
for line in loglines:
print line
首先,我使用上下文管理器(也就是 with
语句)打开文件,这样在你用完文件后或者出现异常时,它会自动关闭。接着,在底部我展示了如何使用 .next()
方法,这样你可以手动一步一步地执行。这在某些情况下很有用,特别是当你需要把逻辑从简单的 for item in gen
循环中分离出来时。
如果你手里只有一把锤子,所有东西看起来都像钉子。
我几乎想用这句话来回答这个问题。仅仅因为你能做到,并不意味着你每次都需要这样做。
从概念上讲,生成器版本把功能分开了,跟随函数的作用是封装从文件中持续读取的过程,同时等待新的输入。这样你就可以在循环中随意处理新的一行内容。在第二个版本中,读取文件和打印的代码和控制循环混在一起。虽然在这个小例子中这可能不是个大问题,但这是你可能需要考虑的事情。