生成器与嵌套for循环

时间:2017-05-06 17:41:05

标签: python python-3.x generator generator-expression

我有两种方法可以对文本文件中的数字求和。第一个工作,第二个工作不工作。任何人都可以解释第二个问题吗?。

输入文字文件:

The quick brown 123
fox 456 jumped over
the 789 lazy dog.

方法#1:

total = 0
for line in open(fn):
    numbers = (int(block) for block in line.split() if block.isdigit())
    total += sum(numbers)
print('total: ', total)

这给出了正确答案1368(= 123 + 456 + 789)。

方法#2:

numbers = (int(block) for block in line.split() for line in open(fn) if block.isdigit())
total = sum(numbers)
print('total: ', total)

这会产生错误:

NameError: name 'line' is not defined

我正在玩发电机,所以问题就在于为什么方法#2中的发电机不好。我不需要有关其他方法的建议,以便在文本文件中添加数字。我想知道是否存在没有标准for循环的仅生成器解决方案。谢谢。

1 个答案:

答案 0 :(得分:2)

你颠倒了循环的顺序。生成器表达式(与所有Python理解语法变体一样)列出块嵌套顺序从左到右的循环。

这有效:

numbers = (int(block) for line in open(fn) for block in line.split() if block.isdigit())

因为它匹配普通for循环的嵌套顺序(前面只有每次迭代表达式):

numbers = (int(block)
    for line in open(fn)
        for block in line.split()
            if block.isdigit())

您的代码尝试在line.split()循环执行之前访问for line in open(fn)并设置line

请参阅expressions reference documentation

  

理解包括单个表达式,后跟至少一个for子句和零个或多个forif子句。在这种情况下,新容器的元素是通过将每个forif子句视为块,从左到右嵌套而生成的元素,以及每次到达最里面的块时,计算表达式以生成一个元素。

大胆强调我的。