1

I use the python's * to create a 2-dimetion list [[0]*10]*10 with a default value 0. But when I set the first element to 1,all the elements of the first colum happend to be 1,why?

This does not happen when I create the list using append(see below variable data ).

#!/bin/env python
#encoding=utf8

width = 10
height = 10

data = []
for i in xrange(width):
    data.append([0 for j in xrange(height)])

data2 = [[0]*width]*height

print "before:",data == data2
data[0][0] = 1
data2[0][0] = 1
print "after:",data == data2

print "actually:"
print data
print data2

output:

before: True
after: False
actually:
[[1, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0]]
[[1, 0, 0, 0, 0, 0, 0, 0, 0, 0], [1, 0, 0, 0, 0, 0, 0, 0, 0, 0], [1, 0, 0, 0, 0, 0, 0, 0, 0, 0], [1, 0, 0, 0, 0, 0, 0, 0, 0, 0], [1, 0, 0, 0, 0, 0, 0, 0, 0, 0], [1, 0, 0, 0, 0, 0, 0, 0, 0, 0], [1, 0, 0, 0, 0, 0, 0, 0, 0, 0], [1, 0, 0, 0, 0, 0, 0, 0, 0, 0], [1, 0, 0, 0, 0, 0, 0, 0, 0, 0], [1, 0, 0, 0, 0, 0, 0, 0, 0, 0]]
Josh Lee
  • 171,072
  • 38
  • 269
  • 275
Codefor
  • 1,318
  • 2
  • 13
  • 22

2 Answers2

1

The * operator on a list will repeat the objects in the list. But it doesn't make copies of the objects, it repeats the actual objects themselves.

The distinction is subtle, and many times you won't notice it. If the objects are immutable such as numbers or strings, all you can do is replace the object with a different object, and then the members of the list will no longer be the same object.

When the objects in the list can be modified, such as another list, any modification to that object is reflected in all the other repeated references in the list.

There's an awkward workaround:

data3 = [[0]*width for i in range(height)]
Mark Ransom
  • 299,747
  • 42
  • 398
  • 622
0

Here:

[[0]*width]

you only create a single list [0], and then you create another list containing width references to that single object. The key point is that the * operator only evaluates its operands once.

Here:

for i in xrange(width):
    data.append([0 for j in xrange(height)])

you are creating a new list on each iteration that you then append.

Alp
  • 2,766
  • 18
  • 13