Reputation: 6087
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
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:
Upvotes: 0
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
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
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
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