4

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'?

Matthew
  • 28,056
  • 26
  • 104
  • 170
  • 1
    The accepted answer is actually wrong! Look at newacct's answer for a nice little discussion on the difference between by-value and by-reference – Michael Deardeuff Aug 27 '09 at 19:26
  • 1
    I don't agree that it's wrong. The discussion is about terminology, and wants us to say that python passes by reference value instead of saying that it passes by reference. I don't see the difference in that terminology, even from a pedagogical standpoint. – Lennart Regebro Aug 27 '09 at 20:14
  • This is a duplicate of this question: http://stackoverflow.com/questions/986006/python-how-do-i-pass-a-variable-by-reference Sadly for that question the originally accepted answer was also wrong (the now accepted answer is pretty good), just like Stefanos answer. – nikow Aug 27 '09 at 20:28
  • @nikow, yes that is a much better description. – Michael Deardeuff Aug 28 '09 at 04:39
  • 2
    Guys, there's no such thing as "pass by reference". In C, when you PBR, it means that you are copying *a pointer's value* into the stack, instead of the actual value. You always pass by value: the meaning of the value you are passing (actual value or a pointer to the location containing the value) being the difference. That said, PBR is just conventional speech to say that you are passing some entity that refers to something else, and therefore you have no guarantee that what you are passing will not be altered by the callee.In this sense python is PBR, but you see it only with mutable objects – Stefano Borini Aug 28 '09 at 22:14

6 Answers6

11

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
  • 138,652
  • 96
  • 297
  • 431
  • 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 Aug 27 '09 at 18:46
  • 1
    mutable are list, dict and basically everything else. Immutable are strings, tuples, integers, floats. – Stefano Borini Aug 27 '09 at 18:48
  • 1
    frozenset is immutable as well. – Ned Deily Aug 27 '09 at 18:56
  • 3
    Actually they are passed by value. That is the references are passed by value. – Michael Deardeuff Aug 27 '09 at 19:16
  • @StefanoBorini As @Michael pointed, it is passed by 'value' and not by 'reference'. Your explanation is correct, but I think you should fix that. – Oscar Mederos Jun 18 '11 at 08:35
  • @oscar : the point is that the OP understands `by value` and `by reference` in a well defined way. We all agree it's fundamentally inexact as a vision of the world, but my answer wanted to speak the language of the OP, with the technical details left behind. So, I won't correct the answer, but I welcome your comments to point out that a fundamental misunderstanding does exist, and prompts the reader to learn more. – Stefano Borini Jun 18 '11 at 22:37
9

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
  • 119,665
  • 29
  • 163
  • 224
3

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
  • 4,450
  • 25
  • 22
3

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
  • 11,870
  • 3
  • 23
  • 19
  • 3
    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 Aug 27 '09 at 18:49
  • 1
    @Sean, that is called "Pass by value" – Michael Deardeuff Aug 27 '09 at 19:20
1

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

Bastien Léonard
  • 60,478
  • 20
  • 78
  • 95
1

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
  • 18,290
  • 7
  • 46
  • 74
  • About `*=`: http://stackoverflow.com/questions/823561/what-does-mean-in-python/823878#823878 – Bastien Léonard Aug 28 '09 at 13:13
  • Try the same with a list and it shows that it is related to the mutability of the object – may Jan 10 '23 at 17:53
  • @may No, the mutability of the object isn't relevant regarding how the object is being passed. The type of the object could affect how the `*=` operator is implemented (as seen at Bastien's link) but that is a different issue, again related to how Python implements assignment and assignment operations. – Kylotan Feb 02 '23 at 21:08