Todd Curry
Todd Curry

Reputation: 1083

Why are lists linked in Python in a persistent way?

A variable is set. Another variable is set to the first. The first changes value. The second does not. This has been the nature of programming since the dawn of time.

>>> a = 1
>>> b = a
>>> b = b - 1
>>> b
0
>>> a
1

I then extend this to Python lists. A list is declared and appended. Another list is declared to be equal to the first. The values in the second list change. Mysteriously, the values in the first list, though not acted upon directly, also change.

>>> alist = list()
>>> blist = list()
>>> alist.append(1)
>>> alist.append(2)
>>> alist
[1, 2]
>>> blist
[]
>>> blist = alist
>>> alist.remove(1)
>>> alist
[2]
>>> blist
[2]
>>> 

Why is this?

And how do I prevent this from happening -- I want alist to be unfazed by changes to blist (immutable, if you will)?

Upvotes: 2

Views: 415

Answers (5)

glglgl
glglgl

Reputation: 91119

Variable binding in Python works this way: you assign an object to a variable.

a = 4
b = a

Both point to 4.

b = 9

Now b points to somewhere else.

Exactly the same happens with lists:

a = []
b = a
b = [9]

Now, b has a new value, while a has the old one.

Till now, everything is clear and you have the same behaviour with mutable and immutable objects.

Now comes your misunderstanding: it is about modifying objects.

lists are mutable, so if you mutate a list, the modifications are visible via all variables ("name bindings") which exist:

a = []
b = a  # the same list
c = [] # another empty one

a.append(3)
print a, b, c # a as well as b = [3], c = [] as it is a different one

d = a[:] # copy it completely
b.append(9)
# now a = b = [3, 9], c = [], d = [3], a copy of the old a resp. b

Upvotes: 9

Dr. Jan-Philip Gehrcke
Dr. Jan-Philip Gehrcke

Reputation: 35796

The short answer two your question "Why is this?": Because in Python integers are immutable, while lists are mutable.

You were looking for an official reference in the Python docs. Have a look at this section: http://docs.python.org/2/reference/simple_stmts.html#assignment-statements

Quote from the latter:

Assignment statements are used to (re)bind names to values and to modify attributes or items of mutable objects

I really like this sentence, have never seen it before. It answers your question precisely.

A good recent write-up about this topic is http://nedbatchelder.com/text/names.html, which has already been mentioned in one of the comments.

Upvotes: 0

jh314
jh314

Reputation: 27812

What is happening is that you create another reference to the same list when you do:

blist = alist

Thus, blist referes to the same list that alist does. Thus, any modifications to that single list will affect both alist and blist.

If you want to copy the entire list, and not just create a reference, you can do this:

blist = alist[:]

In fact, you can check the references yourself using id():

>>> alist = [1,2]
>>> blist = []
>>> id(alist)
411260888
>>> id(blist)
413871960
>>> blist = alist
>>> id(blist)
411260888
>>> blist = alist[:]
>>> id(blist)
407838672

This is a relevant quote from the Python docs.:

Assignment statements in Python do not copy objects, they create bindings between a target and an object. For collections that are mutable or contain mutable items, a copy is sometimes needed so one can change one copy without changing the other.

Upvotes: 4

hivert
hivert

Reputation: 10667

Python variables are actually not variables but references to objects (similar to pointers in C). There is a very good explanation of that for beginners in http://foobarnbaz.com/2012/07/08/understanding-python-variables/

One way to convince yourself about this is to try this:

a=[1,2,3]
b=a
id(a)
68617320
id(b)
68617320

id returns the memory address of the given object. Since both are the same for both lists it means that changing one affects the other, because they are, in fact, the same thing.

Upvotes: 10

Woot4Moo
Woot4Moo

Reputation: 24336

Based on this post:

Python passes references-to-objects by value (like Java), and everything in Python is an object. This sounds simple, but then you will notice that some data types seem to exhibit pass-by-value characteristics, while others seem to act like pass-by-reference... what's the deal?

It is important to understand mutable and immutable objects. Some objects, like strings, tuples, and numbers, are immutable. Altering them inside a function/method will create a new instance and the original instance outside the function/method is not changed. Other objects, like lists and dictionaries are mutable, which means you can change the object in-place. Therefore, altering an object inside a function/method will also change the original object outside.

So in your example you are making the variable bList and aList point to the same object. Therefore when you remove an element from either bList or aList it is reflected in the object that they both point to.

Upvotes: 1

Related Questions