开发者

Whats the correct way of writing this list comprehension?

I'm getting an error: name 'i' is not defined

k = [ [ rids[i][j][0]['a'] * rids[i][j][1]['b']  for i in range(0,10) ] 
     for j in range(0,len(furs[i])) ]

but

k = [ rids[i][j][0]['a'] * rids[i][j][1]['b']   for i in range(0,10)  
     for j in range(0,len(furs[i])开发者_StackOverflow) ]

works surprisingly!

EDIT: What is the correct way of writing it them? I'm trying to generate a 2D matrix with i as iterator for outer for loop & j as iterator for inner for loop.


Look carefully at the second for loop: for j in range(0,len(furs[i])). You are referring to i here even though it is created and used in the preceding first list comprehension ([ rids[i][j][0]['a'] * rids[i][j][1]['b'] for i in range(0,10) ]).

The i is limited to the scope of that first comprehension; thereby it is not visible to the second comprehension. Consequently you get the error.

The second variant works because both i and j are declared and used in the same list comprehension.

Let us simplify the snippet a bit. Try this:

>>> [ [ i * j  for i in range(0,10) ] for j in range(0, i) ]

Traceback (most recent call last):
  File "<pyshell#35>", line 1, in <module>
    [ [ i * j  for i in range(0,10) ] for j in range(0, i) ]
NameError: name 'i' is not defined
>>> 

Now combine the comprehensions, thereby bringing i and j into the same scope:

>>> [ i * j   for i in range(0,10)  for j in range(0, i) ]
[0, 0, 2, 0, 3, 6, 0, 4, 8, 12, 0, 5, 10, 15, 20, 0, 6, 12, 18, 24, 
 30, 0, 7, 14, 21, 28, 35, 42, 0, 8, 16, 24, 32, 40, 48, 56, 0, 9, 
 18, 27, 36, 45, 54, 63, 72]
>>> 

Now (cheeky =P) try the first comprehension again:

>>> [ [ i * j  for i in range(0,10) ] for j in range(0, i) ]
[[0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 1, 2, 3, 4, 5, 6, 7, 8, 9], 
 [0, 2, 4, 6, 8, 10, 12, 14, 16, 18], [0, 3, 6, 9, 12, 15, 18, 21, 24, 27], 
 [0, 4, 8, 12, 16, 20, 24, 28, 32, 36], [0, 5, 10, 15, 20, 25, 30, 35, 40, 45], 
 [0, 6, 12, 18, 24, 30, 36, 42, 48, 54], [0, 7, 14, 21, 28, 35, 42, 49, 56, 63], 
 [0, 8, 16, 24, 32, 40, 48, 56, 64, 72]]
>>> 

Ta da! It works but gives a different result. Why is this so? The reason is that the (last) value of i is available in the outermost scope after example two. That is, variables created inside a list comprehension are available in the REPL scope.

(PS: I believe the above paragraph can be reworded. Better Pythonistas here, please help out)

To verify this, try deleting i and run example 3 again.

>>> del i
>>> [ [ i * j  for i in range(0,10) ] for j in range(0, i) ]

Traceback (most recent call last):
  File "<pyshell#41>", line 1, in <module>
    [ [ i * j  for i in range(0,10) ] for j in range(0, i) ]
NameError: name 'i' is not defined
>>> 

And we are back to square one.


for j in range(0,len(furs[i])) in your first example: i is not in scope here, due to the preceding ].


k = [ [ rids[i][j][0]['a'] * rids[i][j][1]['b']
for i in range(0,10) ] for j in range(0,len(furs[i])) ]
In the above statement i exists only till the first ] and i is out of scope after that.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜