误解了python的收益率

A.M*_*nov 6 python yield generator

以下代码的工作正确:

def file_gen(f_name):
    f = open(f_name)
    for line in f:
        yield line

gen_line = file_gen("foo.html")
gen_line.next() # '<!DOCTYPE>\n'
gen_line.next() # '<html> \n' 
gen_line.next() # ... next line in file 
Run Code Online (Sandbox Code Playgroud)

但是这个功能提升了StopIteration.我不明白为什么?

def file_gen(f_name):
    f = open(f_name)
    line = f.readline()
    yield line

gen_line = file_gen('foo.html')
gen_line.next()  # '<!DOCTYPE>\n'
gen_line.next()  # StopIteration
Run Code Online (Sandbox Code Playgroud)

daw*_*awg 5

你有:

def file_gen(f_name):
    f = open(f_name)
    line = f.readline()
    yield line
Run Code Online (Sandbox Code Playgroud)

注意line = f.readline()这仅从文件读取1行。

比较:

def g(x):
    li=range(x)
    yield li.pop()

print list(g(10))
# [9]
Run Code Online (Sandbox Code Playgroud)

有了这个:

def g(x):
    li=range(x)
    while li:
       yield li.pop()

print list(g(10))
# [9, 8, 7, 6, 5, 4, 3, 2, 1, 0]
Run Code Online (Sandbox Code Playgroud)

yield只能与特定对象或表达式调用一次。一旦接收器使用了它,就必须重新生成它。因此,您需要围绕读取文件的每一行进行循环。

您可以通过以下方式使用第二种形式(可读性较低):

def file_gen(f_name):
    f = open(f_name)
    while True:
        line = f.readline()
        if not line:
            break
        yield line
Run Code Online (Sandbox Code Playgroud)

您需要一个循环来创建要产生的项目。在第一种情况下,for line in f: yield line是一个循环。

我会这样重写您的函数:

def file_gen(f_name):
    with open(f_name) as f:
        for line in f:
            yield line
Run Code Online (Sandbox Code Playgroud)

  • 更具体地说,您只调用一次yield,因此对next()的下一次调用会到达生成器的末尾。 (2认同)