views:

574

answers:

6

In C++, void somefunction(int) passes a value, while void somefunction(int&) passes a reference. In Java, primitives are passed by value, while objects are passed by reference. How does python make this decision?

Edit: Since everything is passed by reference, why does this:

def foo(num):
    num *= 2

a = 4
foo(a)

print(a)

print '4' instead of '8'?

+1  A: 

Everything is passed by reference. Everything is an object, too.

Bastien Léonard
Everything is **an** object, too.
voyager
@voyager: thanks, fixed.
Bastien Léonard
Actually they are passed by value. That is the references are passed by value.
Michael Deardeuff
@Michael: I think everyone agrees on the fact that the references are passed by value. What's your point?
Bastien Léonard
I believe Michael's point is that in other languages, "call by reference" implies that changes of the parameters inside the function typically are visible outside the function, which is not exactly what happens in python. Also, python has no variables; only objects and names.
ΤΖΩΤΖΙΟΥ
The Python language reference uses the word “variable” all the time. Stop trolling please.
Bastien Léonard
+7  A: 

It passes everything by reference. Even when you specify a numeric value, it is a reference against a table containing that value. This is the difference between static and dynamic languages. The type stays with the value, not with the container, and variables are just references towards a "value space" where all values live. You can assume this value space containing all the possible immutable objects (integers, floats, strings) plus all the mutable ones you create (lists, dicts, objects). Of course, their existence is made concrete only when you involve them (that means, if you never use the number 42 in your program, no allocated space exist for the value 42 in the "value space")

It does that because the number it is referring to is a immutable object. 4 is 4 no matter what.

def foo(num): # here, num is referring to the immutable entity 4
    num *= 2  # num now refers to the immutable entity 8

a = 4        # a now is pointing to the immutable entity 4
foo(a)       # a is still referring to the same entity 4

print(a)     # prints what a refers to, still 4

However, if you do this

def foo(l):      # here, l refers to the list it receives
    l.append(5)  # the list is appended with the number 5

a = []       # a now is pointing to a specific mutable list 
foo(a)       # a is still referring to the same specific mutable list

print(a)     # prints what a refers to, the specific mutable list which now contains [5]
Stefano Borini
Thanks for your answer. I guess that's similar to the way `String` works in Java. Is there a list somewhere of what the immutable objects in python are?
Matthew
mutable are list, dict and basically everything else. Immutable are strings, tuples, integers, floats.
Stefano Borini
frozenset is immutable as well.
Ned Deily
Actually they are passed by value. That is the references are passed by value.
Michael Deardeuff
+3  A: 

In response to your edit, it is because integers are immutable in Python. So a is not changed for the same reason it is not changed when running this code:

a = 4
num = a
num *= 2
print(a)

You aren't changing num (and therefore a) in place, you are creating a new number and assigning it to num.

Sean Nyman
+3  A: 

Arguments are actually passed by value. The function is passed the object the variable refers to, not the variable itself. A function cannot rebind a caller's variables. A function cannot change an immutable object, but can change (request changes to) a mutable one.

Anon
Technically, they are passed by assignment. So the parameters are assigned the object that the arguments point to. This is why reassigning a parameter will not reassign the argument, because assignment changes the variable, while method calls change the object.
Sean Nyman
@Sean, that is called "Pass by value"
Michael Deardeuff
+8  A: 

There is disagreement on terminology here. In the Java community, they say that everything is passed by value: primitives are passed by value; references are passed by value. (Just search this site for Java and pass by reference if you don't believe this.) Note that "objects" are not values in the language; only references to objects are.

The distinction that they use is that, in Java, when you pass a reference, the original reference variable in the caller's scope can never be changed (i.e. made to point to a different object) by the callee, which should be possible in pass by reference. Only the object pointed to by the reference may be mutated, but that is irrelevant.

Python values work the exact same way as references in Java. If we use the same definition, then we would say that everything in Python is a reference, and everything is passed by value. Of course, some in the Python community use a different definition.

The disagreement on terminology is the source of most of the confusion.

Since you mention C++, the Python code you have would be equivalent to something like this in C++:

void foo(const int *num) {
    num = new int(*num * 2);
}

const int *a = new int(4);
foo(a);

print(a);

Note that the argument is a pointer, which is most similar to references in Java and Python.

newacct
+1  A: 

This is not really about the function call semantics but the assignment semantics. In Python assignment is done by rebinding the reference, not by overwriting the original object. This is why the example code prints 4 instead of 8 - it has nothing to do with mutability of objects as such, more that the *= operator is not a mutator but a multiplication followed by an assignment. Here the num *= 2 is essentially rebinding the 'num' name in that function to a new object of value 'num * 2'. The original value you passed in is left unaltered throughout.

Kylotan
About `*=`: http://stackoverflow.com/questions/823561/what-does-mean-in-python/823878#823878
Bastien Léonard