Search code examples
pythonlist

Python assigning multiple variables to same value? list behavior


I tried to use multiple assignment as show below to initialize variables, but I got confused by the behavior, I expect to reassign the values list separately, I mean b[0] and c[0] equal 0 as before.

a=b=c=[0,3,5]
a[0]=1
print(a)
print(b)
print(c)

Result is:

[1, 3, 5]
[1, 3, 5]
[1, 3, 5]

Is that correct? what should I use for multiple assignment? what is different from this?

d=e=f=3
e=4
print('f:',f)
print('e:',e)

result:

f: 3
e: 4

Solution

  • If you're coming to Python from a language in the C/Java/etc. family, it may help you to stop thinking about a as a "variable", and start thinking of it as a "name".

    a, b, and c aren't different variables with equal values; they're different names for the same identical value. Variables have types, identities, addresses, and all kinds of stuff like that.

    Names don't have any of that. Values do, of course, and you can have lots of names for the same value.

    If you give Notorious B.I.G. a hot dog,* Biggie Smalls and Chris Wallace have a hot dog. If you change the first element of a to 1, the first elements of b and c are 1.

    If you want to know if two names are naming the same object, use the is operator:

    >>> a=b=c=[0,3,5]
    >>> a is b
    True
    

    You then ask:

    what is different from this?

    d=e=f=3
    e=4
    print('f:',f)
    print('e:',e)
    

    Here, you're rebinding the name e to the value 4. That doesn't affect the names d and f in any way.

    In your previous version, you were assigning to a[0], not to a. So, from the point of view of a[0], you're rebinding a[0], but from the point of view of a, you're changing it in-place.

    You can use the id function, which gives you some unique number representing the identity of an object, to see exactly which object is which even when is can't help:

    >>> a=b=c=[0,3,5]
    >>> id(a)
    4473392520
    >>> id(b)
    4473392520
    >>> id(a[0])
    4297261120
    >>> id(b[0])
    4297261120
    
    >>> a[0] = 1
    >>> id(a)
    4473392520
    >>> id(b)
    4473392520
    >>> id(a[0])
    4297261216
    >>> id(b[0])
    4297261216
    

    Notice that a[0] has changed from 4297261120 to 4297261216—it's now a name for a different value. And b[0] is also now a name for that same new value. That's because a and b are still naming the same object.


    Under the covers, a[0]=1 is actually calling a method on the list object. (It's equivalent to a.__setitem__(0, 1).) So, it's not really rebinding anything at all. It's like calling my_object.set_something(1). Sure, likely the object is rebinding an instance attribute in order to implement this method, but that's not what's important; what's important is that you're not assigning anything, you're just mutating the object. And it's the same with a[0]=1.


    * Warning: Do not give Notorious B.I.G. a hot dog. Gangsta rap zombies should never be fed after midnight.