1

Possible Duplicate:
Two separate python lists acting as one

This code creates a dictionary of lists, the keys being in usens. The lists are full of 0s

usens = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 14, 110, 111, 112, 113, 114,
         115, 116, 117, 118, 119, 302, 303, 306, 307, 308, 370, 371, 500,
         501, 1000, 1010, 1020, 1100, 1200, 1201, 1202, 2000, 2001, 2002
         ]
empty = [[0]*length]*len(usens)
data = dict(zip(usens, empty))
pprint.pprint(data, indent=5)

data[0][0] += 1
pprint.pprint(data, indent=5)

The first pretty print returns the expected (blurb removed):

{0: [0, 0, 0, 0, 0],
 1: [0, 0, 0, 0, 0],
 2: [0, 0, 0, 0, 0],
 3: [0, 0, 0, 0, 0],
 4: [0, 0, 0, 0, 0],
 5: [0, 0, 0, 0, 0],
 .....
 2001: [0, 0, 0, 0, 0],
 2002: [0, 0, 0, 0, 0]}

I then do this: data[0][0] += 1, expecting the first list (of index 0) to begin with 1, but nothing else to change.

However, all the lists have been modified:

{0: [1, 0, 0, 0, 0],
 1: [1, 0, 0, 0, 0],
 2: [1, 0, 0, 0, 0],
 3: [1, 0, 0, 0, 0],
 4: [1, 0, 0, 0, 0],
 .....
 2001: [1, 0, 0, 0, 0],
 2002: [1, 0, 0, 0, 0]}

Why, and how can I make it so only one list is modified?

Community
  • 1
  • 1
ACarter
  • 5,688
  • 9
  • 39
  • 56
  • possible duplicate of [Two separate python lists acting as one](http://stackoverflow.com/questions/9969609/two-separate-python-lists-acting-as-one) and also see [Yet another list aliasing conundrum](http://stackoverflow.com/questions/8997559), – James Waldby - jwpat7 Dec 07 '12 at 20:49

2 Answers2

3

empty = [[0]*length]*len(usens) will create len(usens) copies of the same list, which is different from len(usens) lists with the same content.

Try empty = [[0]*length for i in range(len(usens))].

Imre Kerr
  • 2,388
  • 14
  • 34
1

Using * creates copies; for [0] it's fine, because it's copying an immutable scalar; but the outer * creates copies of the same list (i.e., copies a reference). You could use something like:

empty = [0]*5
data = {n:list(empty) for n in usens}

(a dict comprehension) to create your list (if using Python 2.7+). Using list makes a copy.

dbrobins
  • 499
  • 1
  • 3
  • 9
  • Actually, using `*` *doesn't* create copies. It's the lack of copies that's the problem. You have numerous references to the same list, rather than the copies you thought you were getting. – kindall Dec 07 '12 at 20:55
  • Depends on how one uses the word "copy". It creates copies of the reference; not different references with copies of the value(s) (as a `copy.deepcopy` would). It'd probably be clearer if he said "multiple references" though. – Anorov Dec 07 '12 at 21:40