Posts: 48
Threads: 22
Joined: Mar 2019
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.
Posts: 4,220
Threads: 97
Joined: Sep 2016
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.
Posts: 48
Threads: 22
Joined: Mar 2019
(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)?
Posts: 4,220
Threads: 97
Joined: Sep 2016
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.
Posts: 101
Threads: 5
Joined: Jul 2019
(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
Posts: 4,783
Threads: 76
Joined: Jan 2018
Aug-20-2019, 06:08 AM
(This post was last modified: Aug-20-2019, 06:10 AM by Gribouillis.)
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
Posts: 2,122
Threads: 10
Joined: May 2017
(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.
Posts: 2,953
Threads: 48
Joined: Sep 2016
>>> 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.
Posts: 101
Threads: 5
Joined: Jul 2019
(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'
Posts: 4,783
Threads: 76
Joined: Jan 2018
Aug-21-2019, 06:33 AM
(This post was last modified: Aug-21-2019, 06:34 AM by Gribouillis.)
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
|