I recently discovered that Python list assignment does not work quite the way I expected it to, as illustrated below:

>>> a = [1,2,3]
>>> b = a
>>> b.append(4)
>>> b
[1, 2, 3, 4]
>>> a
[1, 2, 3, 4]
>>>

I was expecting this to create a copy of "a", store it as "b", and then modify "b", leaving "a" unchanged. Python seems to behave this way with respect to any operation which modifies lists in place.

It's simple enough to work around this (by entering ">>> b=[x for x in a]", for example), but I'm still confused by it. Is this just a random quirk in Python, or am I failing to grasp something deeper about the way the language works?

Hi!

This question is not dumb, in fact it's probably the most frequently asked one on the net :)
Maybe these lines will help you (btw, id() returns the memory address of an object):

>>> a = [1,2,3]
>>> b = a
>>> c = a[:]
>>> id(a)
-1210949716
>>> id(b)
-1210949716
>>> id(c)
-1210937204
>>> a[0] = 100
>>> a
[100, 2, 3]
>>> b
[100, 2, 3]
>>> c
[1, 2, 3]

What about nested lists?

>>> a = [[1,1,1], [2,2,2], [3,3,3]]
>>> b = a[:]
>>> a[0][0] = 100
>>> a
[[100, 1, 1], [2, 2, 2], [3, 3, 3]]
>>> b
[[100, 1, 1], [2, 2, 2], [3, 3, 3]]

Woops!

>>> import copy
>>> b = copy.deepcopy(a)
>>> a[0][1] = 100
>>> a
[[100, 100, 1], [2, 2, 2], [3, 3, 3]]
>>> b
[[100, 1, 1], [2, 2, 2], [3, 3, 3]]

In case you wonder, there are the same "problems" with dictionaries, but they have their own copy() method:

>>> a = {'a': 1, 'b': 2}
>>> b = a
>>> a['a'] = 100
>>> a
{'a': 100, 'b': 2}
>>> b
{'a': 100, 'b': 2}
>>> b = a.copy()
>>> a['b'] = 100
>>> a
{'a': 100, 'b': 100}
>>> b
{'a': 100, 'b': 2}

Regards, mawe

With mutable objects like lists and dictionaries you have to be careful with direct assignments. Yes, it makes a copy, but a copy that shares the same address.

>>> a = [1,2,3]
# this makes b an alias of a, they both share the same address
>>> b = a
>>> id(a)
10317136
>>> id(b)
10317136
# this makes a true copy of a, b has its own address
>>> b = list(a)
>>> id(b)
10317216
# now append only affects list a
>>> a.append(4)
>>> a
[1, 2, 3, 4]
>>> b
[1, 2, 3]
>>>

When you share the address of a mutable object, and you change an element within the object, the address of that object is still the same. Immutable objects like numbers or strings behave different of course, when you change their value, you get a new object with its own new address. Hopefully, this will all sink in.

Note: Listen to what mawe has to say!!!!!

This question has already been answered. Start a new discussion instead.