views:

111

answers:

5
+1  Q: 

Python references

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
A: 

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
+2  A: 

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
Is it not possible to get references to immutable objects?
hekevintran
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
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
@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
@Max: 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
+4  A: 

The best explanation I ever read is here: http://python.net/~goodger/projects/pycon/2007/idiomatic/handout.html#other-languages-have-variables

LeMiz
+1: That's an excellent short and to the point explanation.
Max Shawabkeh
+1  A: 

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
A: 

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