When we define a variable, basically we are naming a memory address
This is incorrect, for other languages, but not for python.
In python, there are no variables. What exists are names; The best analogy I’ve found are paper labels with a name on it.
In python, there are no different values. Only exists a single type of value, that is "reference". In python, variables (names) do not represent memory addresses as in some other languages. The names keep only references, who allocates and uses memory are the objects themselves and not the names.
In short, actually what we have are names and references. Each name holds a value that is a reference to an object.
When an object no longer has any reference to it, it is removed from memory and the space it occupied is automatically released.
For example:
x = 5
After executing the above line, x
is declared as a name that has a reference to the object of type int
5
y = x
Now, y
is another name that has a reference to same object that x. At this point we have only one object in memory, the 5
; We have two names x
and y
both have references to the same object 5
.
x = x + 1
Now we are performing a sum operation, ie, int.__add__(x, 1)
that calf and returns a new object of the type int
, the 6
. From that point on x
has a reference to this new object int
. The name y
continues to refer to the object 5
. We therefore have two names and two objects in memory.
The situation complicates when using mutable objects as lists:
a = []
b = a
a.append('Teste')
In the example above, there is only one list, created in the first line of that piece of code. The method append()
does not create a new list, he modifies the existing list you refer to, so you still have two names a
and b
referring to the same object.
def func(x):
x = 2
a = []
func(a)
If the passage were by reference, x = 2
would alter a
; however, the passage is by value, and the value is a reference. x = 2
simply makes the local name x
refers to another object, the 2
; The name a
continues to refer to the list []
. It is impossible to change the value of a
(which is a reference) through the parameter x
, because that reference has been passed by value into the function func
.
You can use the reference you passed to modify the object itself, if it is mutable, but you cannot use it to modify who the name you passed refers to.
In python, all parameter passages and all returns are for value however this value is always a reference! It is not the same as passing by reference, as it is impossible, from within the function, to change the reference of the name that was passed as parameter.
Is there any other way to avoid returning the Python reference?
In his first example, the return
is returning the value associated with the name _value
, but this value is a reference to the list previously created:
return cls._value
That is, this way of functioning is part of the language and there is no way to modify it. All passages are by value and all values will always be references.
Your answer is wrong. In the example that says "But be careful when using this function" the code does not behave the way you put it in the answer. The
copy
is enough in that case, it is not necessary to usedeepcopy
as there are no lists within lists.– nosklo
@nosklo, really, I made a mistake with the prints and ended up talking nonsense. I edited the answer.
– AlexCiuffa