Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How does python decide whether a parameter is a reference or a value?

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

like image 242
Matthew Avatar asked Nov 27 '22 15:11

Matthew


2 Answers

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]
like image 192
Stefano Borini Avatar answered Dec 20 '22 00:12

Stefano Borini


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.

like image 39
newacct Avatar answered Dec 20 '22 02:12

newacct