15

Can someone explain why the example with integers results in different values for x and y and the example with the list results in x and y being the same object?

x = 42
y = x
x = x + 1
print x # 43
print y # 42

x = [ 1, 2, 3 ]
y = x
x[0] = 4
print x # [4, 2, 3]
print y # [4, 2, 3]
x is y # True
SilentGhost
  • 307,395
  • 66
  • 306
  • 293
hekevintran
  • 22,822
  • 32
  • 111
  • 180
  • wow! this looks just like what i was asking last month in http://stackoverflow.com/questions/2573135/2573965#2573965 – wescpy May 10 '10 at 04:30

4 Answers4

8

Because integers are immutable, while list are mutable. You can see from the syntax. In x = x + 1 you are actually assigning a new value to x (it is alone on the LHS). In x[0] = 4, you're calling the index operator on the list and giving it a parameter - it's actually equivalent to x.__setitem__(0, 4), which is obviously changing the original object, not creating a new one.

Max Shawabkeh
  • 37,799
  • 10
  • 82
  • 91
  • Is it not possible to get references to immutable objects? – hekevintran May 09 '10 at 10:06
  • 3
    All "variables" are references. Th difference is that you cannot change immutable objects. Once they are created, they never change - any attempted change will create a new object. – Max Shawabkeh May 09 '10 at 10:11
  • 2
    Stating "assigning a new value to x" is disingenuous and potentially confusing. What is happening is that a reference to a new object (result of x + 1) is bound to the name x. Python does not have the concept of lvalue/rvalue as everything is referenced - so the distinction is important. – Jeremy Brown May 09 '10 at 13:02
  • @Jeremy Brown: I stand by my wording. The new value is the object created from evaluating the expression `x + 1`. After the assignment (that's what it is called in the Python documentation) `x` refers to the new value. And there's a concept of rvalue/lvalue in Python. It's not the same as in other languages, but it is there - that's why the left side of the `=` has to be a (usually singular) sequence of identifiers, not an expression, in the basic assignment statement. See: http://docs.python.org/reference/simple_stmts.html#grammar-token-assignment_stmt – Max Shawabkeh May 09 '10 at 13:29
  • 1
    Note the wording of the first sentence (emphasis mine) - "Assignment statements are used to *(re)bind* names to values..." rvalue/lvalue has very specific meaning for C-like languages (this is not a general BNF concept). Your wording implies that there is a memory "slot" to which a value is assigned. That's not the case in Python and that's why you can't overload the assignment operator. I merely suggest using terms such as bind/rebind to completely disambiguate how assignment works. The most common pitfall I see with new Python programmers is not understanding that reference concept. – Jeremy Brown May 10 '10 at 00:18
4

If you do y = x, y and x are the reference to the same object. But integers are immutable and when you do x + 1, the new integer is created:

>>> x = 1
>>> id(x)
135720760
>>> x += 1
>>> id(x)
135720748
>>> x -= 1
>>> id(x)
135720760

When you have a mutable object (e.g. list, classes defined by yourself), x is changed whenever y is changed, because they point to a single object.

Krab
  • 2,118
  • 12
  • 23
0

That's because when you have a list or a tuple in python you create a reference to an object. When you say that y = x you reference to the same object with y as x does. So when you edit the object of x y changes with it.

Bloeper
  • 347
  • 2
  • 3
  • 13
  • 2
    “when you have a list or a tuple” is pretty misleading. – Ry- Jun 20 '13 at 14:01
  • Yeah I'm sorry about that. What I meant to say was that it doesn't matter which of the two, since they are both immutable. – Bloeper Jul 19 '13 at 08:29
0

As the previous answers said the code you wrote assigns the same object to different names such aliases. If you want to assign a copy of the original list to the new variable (object actually) use this solution:

>>> x=[1,2,3]
>>> y=x[:] #this makes a new list
>>> x
[1, 2, 3]
>>> y
[1, 2, 3]
>>> x[0]=4
>>> x
[4, 2, 3]
>>> y
[1, 2, 3]
sipiatti
  • 904
  • 1
  • 9
  • 21