You are altering a mutable value, so you need to make an explicit copy:
bar = list(foo)
or
bar = foo[:]
When assigning to a name in Python, all you do is store a reference to the value. Without creating a copy of the list, both foo
and bar
referred to the same list.
For non-mutable values this is not a problem; you replace a reference to, say, a string to point to a different value instead.
But lists (and dict
and set
and instances of most classes) are mutable. You didn't change foo
, you changed the value foo
refers to. You did foo.append(9)
, which Python sees as:
- Find the value
foo
refers to.
- Find the attribute
.append
on that value. This returns a method on a list instance.
- Call the method, passing in the value
9
. This alters the list.
Python names themselves are nothing more than labels, pointing to actual values. You could see the values as balloons, the names as little paper tags, and assignment is the act of tying the labels to the balloons. bar = foo
created a second paper tag, that was tied to the exact same balloon.
See this older answer of mine where I push the balloon metaphor around some more.