Python Forum

Full Version: Passing an argument by reference
You're currently viewing a stripped down version of our content. View the full version with proper formatting.
Pages: 1 2
Can you pass an argument by reference with data structures other than lists?

def try_to_change_list_contents(the_list):
    print('got', the_list)
    the_list.append('four')
    print('changed to', the_list)

outer_list = ['one', 'two', 'three']

print('before, outer_list =', outer_list)
try_to_change_list_contents(outer_list)
print('after, outer_list =', outer_list)
This will alter a list. Can you pass an argument by reference to alter other data structures, like variables? I tried to alter a variable this way, and it didn't work for me.
The issue is whether the data type is mutable or immutable. Lists, sets, and dictionaries are mutable and are passed by reference. Tuples, strings, frozensets, ints, and floats are immutable and are passed by value.

Note that user created classes are considered to be immutable, and thus passed by reference. So you could make a class that is a wrapper for an immutable type to pass it sort of by reference. Of course, it would probably be easier to pass it as a one item list.
(Aug-10-2019, 03:49 PM)ichabod801 Wrote: [ -> ]The issue is whether the data type is mutable or immutable. Lists, sets, and dictionaries are mutable and are passed by reference. Tuples, strings, frozensets, ints, and floats are immutable and are passed by value.

Note that user created classes are considered to be immutable, and thus passed by reference. So you could make a class that is a wrapper for an immutable type to pass it sort of by reference. Of course, it would probably be easier to pass it as a one item list.

If a variable contains an immutable data type, does that make the variable immutable (for the purposes of passing an argument by reference)?
Yes. In fact reference/value comes into play with variables themselves. Take this:

x = 5
y = x
a = [5]
b = a

y += 8
b.append(8)
At the end of this, x will still be 5. Since ints are immutable, the assignment was done by value. The value of a, however, will be [5, 8]. Since a list is mutable, it was assigned by reference.
(Aug-10-2019, 03:49 PM)ichabod801 Wrote: [ -> ]The issue is whether the data type is mutable or immutable. Lists, sets, and dictionaries are mutable and are passed by reference. Tuples, strings, frozensets, ints, and floats are immutable and are passed by value. Note that user created classes are considered to be immutable, and thus passed by reference. So you could make a class that is a wrapper for an immutable type to pass it sort of by reference. Of course, it would probably be easier to pass it as a one item list.

Can you please give some hint on creating a wrapper class which will work on immutable class
Exsul Wrote:Can you pass an argument by reference to alter other data structures, like variables? I tried to alter a variable this way, and it didn't work for me.
Python never calls 'by value' in the sense that it doesn't make a copy of any function's argument. For each argument, it copies only the address of a python object which is a 'value' in the python sense. So this discussion about call by value and call by reference is ambiguous. Python passes only addresses of structures used as values.

What python cannot do (and this is the way I understand your question) is pass a reference to a variable as you would do in C when you write foo(&x) for example. The only way to reference a variable in python is to do it symbolically, that is to say if the variable is named 'x', use the word 'x'. So a python function cannot easily change the value of a variable in the calling environment. The usual workaround is to change the value of instances attributes, for example

def func(a):
    a.foo = 5 # changes the value of attribute foo of object a
(Aug-10-2019, 03:49 PM)ichabod801 Wrote: [ -> ]The issue is whether the data type is mutable or immutable. Lists, sets, and dictionaries are mutable and are passed by reference. Tuples, strings, frozensets, ints, and floats are immutable and are passed by value.

Not complete right. All names are also references also to immutable objects. You still have the reference to the in memory living object, but you can't change the content (str, bytes, tuple, int, float, complex, frozenset).

If you want to affect the outer scope of a function, you can mutate objects inside the function. The other possibility is, to use globals. Don't use them.
>>> x = 0
>>> def inc(number):
...     print(id(x))
...     print(id(number))
...     number += 1
...     print(id(x))
...     print(id(number))
...     return number
...
>>> inc(x)
140718032253152
140718032253152
140718032253152
140718032253184
1
>>>
The local "variable" number is a reference to x. They have the same memory address. Then number is increased by 1. Because the integers are immutable type this operation can't change the value of x and a new variable with value 1 with a new address is created and now number is pointing to it. This is how memory in Python works. All names are references to an object and then it comes if they are mutable or not.
As already stated the names keep the memory address to a variable. So these addresses are passed as an argument.
(Aug-20-2019, 06:08 AM)Gribouillis Wrote: [ -> ]
Exsul Wrote:Can you pass an argument by reference to alter other data structures, like variables? I tried to alter a variable this way, and it didn't work for me.
Python never calls 'by value' in the sense that it doesn't make a copy of any function's argument. For each argument, it copies only the address of a python object which is a 'value' in the python sense. So this discussion about call by value and call by reference is ambiguous. Python passes only addresses of structures used as values. What python cannot do (and this is the way I understand your question) is pass a reference to a variable as you would do in C when you write foo(&x) for example. The only way to reference a variable in python is to do it symbolically, that is to say if the variable is named 'x', use the word 'x'. So a python function cannot easily change the value of a variable in the calling environment. The usual workaround is to change the value of instances attributes, for example
 def func(a): a.foo = 5 # changes the value of attribute foo of object a 

I tried to change the value of the instance attribute in this way

 def f(a):
...     a.foo =5
...     print(foo)
...
>>> foo=6
>>> f(1)
If I run like above, I'm hitting
Error:
Traceback (most recent call last): File "<stdin>", line 1, in <module> File "<stdin>", line 2, in f AttributeError: 'int' object has no attribute 'foo'
Malt Wrote:I tried to change the value of the instance attribute in this way
You can't change the value of global variables this way, and you can't add attributes to builtin types which are not defined in pure python. You can use it to add attributes of user defined types, for example:
class Spam:
    pass

def func(a):
    a.foo = 5

s = Spam()
func(s)
print(s.foo) # prints 5
Pages: 1 2