1

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?

FlyingTeller
  • 17,638
  • 3
  • 38
  • 53
jml
  • 137
  • 1
  • 10

1 Answers1

2

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:

  1. Set i=0, from the for loop:
  • List comprehension generates list of -1's and sets i=2

  • myList[i] = is actually myList[2] =

  1. Set i=1, from the for loop:
  • List comprehension generates list of -1's and sets i=2

  • myList[i] = is actually myList[2] =

  1. Set i=2, from the for loop:
  • List comprehension generates list of -1's and sets i=2

  • myList[i] = is actually myList[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[i] = [-1 for j in range(COL)]

print('myList2 =', myList)
FlyingTeller
  • 17,638
  • 3
  • 38
  • 53
  • I originally accepted the answer before I tried it. Using `mylist[j]` just causes the same problem, but `mylist[i] = [-1 for j in range(COL)]` seems to do the trick. – jml Jul 21 '22 at 13:54
  • 1
    My bad, it was a typo, fixed it – FlyingTeller Jul 21 '22 at 19:27