user3067926
user3067926

Reputation: 11

Python: Strange list behaviour

So, I am playing around with Python trying to learn how to use it and I discovered something odd. My code is:

list1 = range(0, 2)
list2 = range(2, 4)

comb = list1, list2

print comb
print list1

list1.append(list2)

print comb
print list1

the outputs are:

print comb   ---   ([0, 1], [2, 3])
print list1  ---   [0, 1]

print comb   ---   ([0, 1, [2, 3]], [2, 3])
print list1  ---   [0, 1, [2, 3]]

What seem to be happening is I am combining my two lists, which works fine. But when I append list2 into list1 and re-print my comb list, the comb list has been updated with the newly appended list1.

What am I missing? Why does comb change when it has not been recalculated since the appending of list1?

Upvotes: 0

Views: 132

Answers (5)

user2555451
user2555451

Reputation:

comb contains references to list1 and list2 themselves, not copies of them. Furthermore, this means that comb[0] is in fact list1 and vice-vera.

Below is a demonstration:

>>> list1 = range(0, 2)
>>> list2 = range(2, 4)
>>> comb = list1, list2
>>> id(list1)
28888960
>>> id(comb[0])
28888960
>>>

In the above example, notice how the ids of list1 and comb[0] are the same. What this tells you is that they both reference the same object in memory. So, when you update one, the other will also be updated.


To fix the problem, make comb contain copies of list1 and list2 instead of references:

>>> list1 = range(0, 2)
>>> list2 = range(2, 4)
>>> # [:] creates a shallow copy of the lists.
>>> comb = list1[:], list2[:]
>>> id(list1)
28930176
>>> id(comb[0])
28931696
>>>

As you can see, the ids of list1 and comb[0] are now different. This means that they no longer reference the same object.

Upvotes: 2

fuesika
fuesika

Reputation: 3330

A colleague of mine had this the other day. This effect stems from your

comb = list1, list2

You need to use

comb = list(list1 + list2)

to actually copy the list, cf. http://www.precheur.org/python/copy_list and http://od-eon.com/blogs/bogdan/python-assignment-value-or-reference/

Upvotes: 0

Martijn Pieters
Martijn Pieters

Reputation: 1124768

comb is a tuple, with two references to the same list objects that the list1 and list2 names refer to.

When you appended list2 to list1, you added another reference to that list to list1. Now you have 3 references to that list object. One in list2, another in comb[1] and a third in list1[2].

Whenever you manipulate a list or dictionary or any other mutable object type in Python, all references to that object will reflect those changes, because you are dealing with just one object.

Picture objects as balloons, and names are labels, tied to the balloons with thread. The threads are references. You can tie multiple labels to a balloon, but you'd still have only one balloon, and if you popped the balloon all labels would be tied to the same piece of lifeless rubber.

Lists and tuples are just balloons with numbered labels taped onto them; those labels are tied to other objects. So comb is a balloon with two labels taped on, numbered 0 and 1. Those labels are tied to the same balloons list1 and list2 are tied to as well.

Upvotes: 2

Ignacio Vazquez-Abrams
Ignacio Vazquez-Abrams

Reputation: 799420

comb is composed of list1 and list2. Mutating list1 doesn't change this, and it appears that comb has changed when in reality, it is still exactly the same.

Upvotes: 0

dckrooney
dckrooney

Reputation: 3121

comb holds references to list1 and list2. Thus when you update list1, comb is updated as well.

If you want comb to hold a copy of the data from list1 and list2 instead of a reference, try:

comb = (list1[:], list2[:])

Upvotes: 0

Related Questions