On Sun, Apr 05, 2015 at 11:12:32AM -0300, Narci Edson Venturini wrote: > The next code has an unexpected result: > > >>>a=3*[3*[0]] > >>>a > [[0, 0, 0], [0, 0, 0], [0, 0, 0]] > >>>a[0][0]=1 > >>>a > [[1, 0, 0], [1, 0, 0], [1, 0, 0]]
It isn't obvious, and it is *very* common for people to run into this and be confused, but that is actually working by design. The * operator for lists does not copy the list items, it makes multiple references to it. Let's have a look at an example. We start with an arbitrary object: py> class X: pass ... py> x = X() py> print(x) <__main__.X object at 0xb7a9d92c> Printing the object x shows us the memory location of x: 0xb7a9d92c. Now let us put it in a list, and replicate it: py> mylist = [x]*3 py> print(mylist) [<__main__.X object at 0xb7a9d92c>, <__main__.X object at 0xb7a9d92c>, <__main__.X object at 0xb7a9d92c>] Do you see how *all three* list items have the same memory location? Rather than get three different X objects, we have the same object, repeated three times. So these two lines are essentially identical: mylist = [x]*3 mylist = [x, x, x] Now, in practice, sometimes that makes a difference, and sometimes it doesn't. If you use an int or a str, it makes no difference: py> mylist = [1]*5 py> mylist [1, 1, 1, 1, 1] Let's look at their ID numbers and see that they are identical: py> for item in mylist: ... print(id(item)) ... 136560640 136560640 136560640 136560640 136560640 So it is the same int object repeated five times, not five different objects. But that doesn't matter, since there is no way to change the value of the object: ints are immutable, and 1 is always 1. You can only *replace* the object with a new object: py> mylist[0] = 2 py> print(mylist) [2, 1, 1, 1, 1] Now let's do it again with a list of lists: py> mylist = [[]]*5 py> mylist [[], [], [], [], []] py> for item in mylist: ... print(id(item)) ... 3081330988 3081330988 3081330988 3081330988 3081330988 So you can see, we now have the same list repeated five times, not five different lists. If we *replace* one of the items, using = assignment, everything behaves as expected: py> mylist[0] = [1,2,3] # Replace the first item. py> print(mylist) [[1, 2, 3], [], [], [], []] But if we modify one of the items, you may be surprised: py> mylist[1].append(999) # Change the second item in place. py> print(mylist) [[1, 2, 3], [999], [999], [999], [999]] The solution to this "gotcha" is to avoid list multiplication except for immutable objects like ints and strings. So to get a 3 x 3 array of all zeroes, I would write: py> array = [[0]*3 for i in range(3)] py> print(array) [[0, 0, 0], [0, 0, 0], [0, 0, 0]] py> array[0][1] += 1 py> print(array) [[0, 1, 0], [0, 0, 0], [0, 0, 0]] -- Steve _______________________________________________ Tutor maillist - Tutor@python.org To unsubscribe or change subscription options: https://mail.python.org/mailman/listinfo/tutor