Ferguzz
Ferguzz

Reputation: 6087

I thought Python passed everything by reference?

Take the following code

#module functions.py
def foo(input, new_val):
    input = new_val

#module main.py
input = 5
functions.foo(input, 10)

print input

I thought input would now be 10. Why is this not the case?

Upvotes: 7

Views: 3126

Answers (5)

Mostafa Wael
Mostafa Wael

Reputation: 3838

Well, python functions are neither call-by-reference nor call-by-value, they are call-by-object. before applying this concept on functions, let's take a look at those code snippets:

1-

listA = [0]
listB = listA
listB.append(1)
print (listA) # [0, 1]

2-

listA = [0]
listB = listA
listB = [2, 3]
print(listA) # [0]

In the first code snippet, listB was able to access the objects stored in listA and modify them BUT IT COULDN'T MODIFY listA in the second code snippet, as they are not the same thing! you passed a container of objects and were able to modify the objects in that container but, you can't modify that container itself. in your code:

def foo(input, new_val):
    input = new_val
input = 5
foo(input, 10)
print (input)

you can't modify the variable 'input' because you don't have it! Passing by object is a very confusing concept and reminds me with Quantum Physics but, try playing around with the code and you will understand it well. you can check the following links for more illustrations:

geeks for geeks

ROBERT HEATON blog

Upvotes: 0

Fred Foo
Fred Foo

Reputation: 363597

Assignment in Python does not modify an object in-place. It rebinds a name so that after input = new_val, the local variable input gets a new value.

If you want to modify the "outside" input, you'll have to wrap it inside a mutable object such as a one-element list:

def foo(input, new_val):
    input[0] = new_val

foo([input])

Python does not do pass-by-reference exactly the way C++ reference passing works. In this case at least, it's more as if every argument is a pointer in C/C++:

// effectively a no-op!
void foo(object *input, object *new_val)
{
    input = new_val;
}

Upvotes: 5

Silas Parker
Silas Parker

Reputation: 8147

Python is neither call-by-value, or call-by-reference, it is Call By Object.

"Arguments are passed by call-by-sharing, similar to call-by-value, except that the arguments are objects and can be changed only if they are mutable."

Upvotes: 4

hochl
hochl

Reputation: 12930

Inside foo, you're binding the local name input to a different object (10). In the calling context, the name input still refers to the 5 object.

Upvotes: 8

Sven Marnach
Sven Marnach

Reputation: 601749

Everything is passed by value, but that value is a reference to the original object. If you modify the object, the changes are visible for the caller, but you can't reassign names. Moreover, many objects are immutable (ints, floats, strings, tuples).

Upvotes: 15

Related Questions