1

What I am trying to achieve is to insert a small 2D-list into a big one (I'm using Python 2.7.3).

Why am I getting different results for var1 and var2?

def modify(foo):
    small = [[1]*2]*2
    for y, line in enumerate(small):
        foo[y+1][1:3] = line
    return foo

var1 = [[0]*4]*4
var2 = [
    [0, 0, 0, 0],
    [0, 0, 0, 0],
    [0, 0, 0, 0],
    [0, 0, 0, 0]]

print modify(var1)
print modify(var2)

# Result:
# var1 = [
#   [0, 1, 1, 0],
#   [0, 1, 1, 0],
#   [0, 1, 1, 0],
#   [0, 1, 1, 0]]
#
# var2 = [
#   [0, 0, 0, 0],
#   [0, 1, 1, 0],
#   [0, 1, 1, 0],
#   [0, 0, 0, 0]]
tfeldmann
  • 3,108
  • 1
  • 23
  • 34

2 Answers2

6

By using [[0]*4]*4 you are in fact creating a single list ([0]*4) and referencing it four times.

>>> var1 = [[0]*4]*4
>>> var1
[[0, 0, 0, 0], [0, 0, 0, 0], [0, 0, 0, 0], [0, 0, 0, 0]]
>>> var1[0][0] = 2
>>> var1
[[2, 0, 0, 0], [2, 0, 0, 0], [2, 0, 0, 0], [2, 0, 0, 0]]
>>> var1[0] is var1[1]
True

It's a little clearer if you replace the inner content with a variable

>> inner = [0]*4
>> var1 = [inner, inner, inner, inner]
>>> var1
[[0, 0, 0, 0], [0, 0, 0, 0], [0, 0, 0, 0], [0, 0, 0, 0]]
>>> inner[0] = 1
>>> var1
[[1, 0, 0, 0], [1, 0, 0, 0], [1, 0, 0, 0], [1, 0, 0, 0]]
Rod
  • 52,748
  • 3
  • 38
  • 55
  • 2
    Everyone comes across this at least once while working with Python. One of those times where Python's hidden use of pointers comes back to bite you. – DaveTheScientist Apr 11 '13 at 19:22
2

[0]*4 creates [0, 0, 0, 0], however, [[0,0,0,0]]*4 creates a list containing shallow copies of [0,0,0,0]. That means, all inner lists are the same.

Elmar Peise
  • 14,014
  • 3
  • 21
  • 40