2017-05-06 118 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