2017-05-06 120 views
1

我有两种方法来总结文本文件中找到的数字。第一个工作,第二个不工作。任何人都可以解释第二个错在什么地方?生成器与嵌套for循环

输入文本文件:

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发电机是没有好。我不需要其他方法在文本文件中添加数字。我想知道是否有一个没有标准循环的纯生成器解决方案。谢谢。

+2

把'for block放在line.split()'后面的'for open line(fn)' –

回答

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

The comprehension consists of a single expression followed by at least one for clause and zero or more for or if clauses. In this case, the elements of the new container are those that would be produced by considering each of the for or if clauses a block, nesting from left to right, and evaluating the expression to produce an element each time the innermost block is reached.

大胆重点煤矿。

+0

谢谢。现在有道理。 – Riccati