Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Python's Passing by References [duplicate]

Hello I am trying to understand how Python's pass by reference works. I have an example:

>>>a = 1 >>>b = 1 >>>id(a);id(b) 140522779858088 140522779858088 

This makes perfect sense since a and b are both referencing the same value that they would have the identity. What I dont quite understand is how this example:

>>>a = 4.4 >>>b = 1.0+3.4 >>>id(a);id(b) 140522778796184 140522778796136 

Is different from this example:

>>>a = 2 >>>b = 2 + 0 >>>id(a);id(b) 140522779858064 140522779858064 

Is it because in the 3rd example the 0 int object is being viewed as "None" by the interpreter and is not being recognized as needing a different identity from the object which variable "a" is referencing(2)? Whereas in the 2nd example "b" is adding two different int objects and the interpreter is allocating memory for both of those objects to be added, which gives variable "a", a different identity from variable "b"?

like image 504
Pulse Avatar asked Mar 20 '17 15:03

Pulse


People also ask

Does Python pass-by-reference or copy?

All parameters (arguments) in the Python language are passed by reference. It means if you change what a parameter refers to within a function, the change also reflects back in the calling function.

Is Python always pass-by-reference?

Python always uses pass-by-reference values. There isn't any exception. Any variable assignment means copying the reference value.

Are objects in Python passed by reference?

As we know, in Python, “Object references are passed by value”. A function receives a reference to (and will access) the same object in memory as used by the caller.

How do you pass a parameter by reference in Python?

All parameters (arguments) in the Python language are passed by reference. It means if you change what a parameter refers to within a function, the change also reflects back in the calling function.


2 Answers

In your first example, the names a and b are both "referencing" the same object because of interning. The assignment statement resulted in an integer with the same id only because it has reused a preexisting object that happened to be hanging around in memory already. That's not a reliable behavior of integers:

>>> a = 257 >>> b = 257 >>> id(a), id(b) (30610608, 30610728) 

As demonstrated above, if you pick a big enough integer then it will behave as the floats in your second example behaved. And interning small integers is optional in the Python language anyway, this happens to be a CPython implementation detail: it's a performance optimization intended to avoid the overhead of creating a new object. We can speed things up by caching commonly used integer instances, at the cost of a higher memory footprint of the Python interpreter.

Don't think about "reference" and "value" when dealing with Python, the model that works for C doesn't really work well here. Instead think of "names" and "objects".

names

The diagram above illustrates your third example. 2 is an object, a and b are names. We can have different names pointing at the same object. And objects can exist without any name.

Assigning a variable only attaches a nametag. And deleting a variable only removes a nametag. If you keep this idea in mind, then the Python object model will never surprise you again.

like image 187
wim Avatar answered Sep 27 '22 17:09

wim


As stated here, CPython caches integers from -5 to 256. So all variables within this range with the same value share the same id (I wouldn't bet on that for future versions, though, but that's the current implementation)

There's no such thing for floats probably because there's an "infinity" of possible values (well not infinite but big because of floating point), so the chance of computing the same value by different means is really low compared to integers.

>>> a=4.0 >>> b=4.0 >>> a is b False 
like image 31
Jean-François Fabre Avatar answered Sep 27 '22 17:09

Jean-François Fabre