I'm trying to initialize a 2-D list using list comprehensions, but I'm seeing different results in Python 2 vs. Python 3 and I have no idea why. Sample code (the import
is just so I can use v3 print statements in v2):
from __future__ import print_function
ROW = 3
COL = 3
myList = [0 for i in range(ROW)]
#print('myList1 =', myList, 'len =', len(myList))
for i in range(len(myList)):
#print('i =', i)
myList[i] = [-1 for i in range(COL)]
#myList[0] = [-1 for i in range(COL)]
print('myList2 =', myList)
Python 3 output: myList2 = [[-1, -1, -1], [-1, -1, -1], [-1, -1, -1]]
Python 2 output: myList2 = [0, 0, [-1, -1, -1]]
The Python 3 behavior is what I would expect, and the commented out print statements are what I used to confirm that everything between the two up until the myList[i]
assignment is the same. If I manually do, e.g., myList[0] =...
outside of the for loop it updates that element as expected. What am I missing here?
CodePudding user response:
You are using i
twice within the same for loop, once in the list-comprehension and once as a run variable for the outer for-loop. As detailed in this post, variables used in a list comprehension "leak" into the surrounding scope in python 2x. So your for loop processes like this:
- Set
i=0
, from the for loop:
List comprehension generates list of
-1
's and setsi=2
myList[i] =
is actuallymyList[2] =
- Set
i=1
, from the for loop:
List comprehension generates list of
-1
's and setsi=2
myList[i] =
is actuallymyList[2] =
- Set
i=2
, from the for loop:
List comprehension generates list of
-1
's and setsi=2
myList[i] =
is actuallymyList[2] =
Which generates the list [0, 0, [-1, -1, -1]]
, because we only ever changed myList[2]
The simplest fix is to use different variables, i.e j in one place:
from __future__ import print_function
ROW = 3
COL = 3
myList = [0 for i in range(ROW)]
for i in range(len(myList)):
#Use j for the list comprehension
myList[j] = [-1 for j in range(COL)]
print('myList2 =', myList)