生成器和文件

时间:2017-08-18 13:54:40

标签: python generator operator-precedence generator-expression

当我写:

lines = (line.strip() for line in open('a_file'))

当我开始使用生成器表达式时,文件是立即打开还是仅访问文件系统?

3 个答案:

答案 0 :(得分:5)

立即打开。如果你使用一个不存在的文件名,你可以验证这个(它会抛出一个异常,表明Python实际上试图立即打开它。)

您还可以使用提供更多反馈的函数,以便在迭代生成器之前查看命令的执行:

def somefunction(filename):
    print(filename)
    return open(filename)

lines = (line.strip() for line in somefunction('a_file'))  # prints

但是,如果使用生成器函数而不是生成器表达式,则仅在迭代时打开文件:

def somefunction(filename):
    print(filename)
    for line in open(filename):
        yield line.strip()

lines = somefunction('a_file')  # no print!

list(lines)                     # prints because list iterates over the generator function.

答案 1 :(得分:4)

无论何时或是否消耗它,都会在生成发生器后立即调用<{open()

相关规范为PEP-289

  

早期结合与晚期结合

     

经过多次讨论,确实如此   决定应该评估第一个(最外面的)for-expression   立即和剩余的表达式进行评估时   生成器被执行。

     

要求总结绑定第一个表达式的原因,   Guido提供了[5]:

     

考虑sum(x for x in foo())。现在假设foo()中有一个错误   引发异常,以及sum()中引发异常的错误   在它开始迭代它的参数之前。会有哪个例外   你期待看到吗?如果sum()中的那个人被提出,我会感到惊讶   而是foo()中的那个,因为对foo()的调用是其中的一部分   sum()的参数,我希望参数在...之前得到处理   函数被调用。

     

OTOH,sum(bar(x) for x in foo())sum()foo()   bugfree,但是bar()引发了异常,我们别无选择,只能拖延   调用bar()直到sum()开始迭代 - 这是...的一部分   发电机合同。 (他们在next()方法之前什么都不做   首先叫。)

有关进一步讨论,请参阅该部分的其余部分。

答案 2 :(得分:1)

立即打开。

示例:

def func():
    print('x')
    return [1, 2, 3]

g = (x for x in func())

输出:

x

该函数需要返回一个可迭代对象。 open()返回一个可迭代的打开文件对象。 因此,在定义生成器表达式时将打开该文件。