I wrote the following code to check if integers are passed by value or reference.
foo = 1
def f(bar):
print id(foo) == id(bar)
bar += 1
print foo, bar
f(foo)
The output I get is
True
1, 2
From the Python documentation, id(object)
returns the identity of an object. In the CPython implementation, this is the address of the object in memory. Since the first statement in the function body returns True
, it means foo
has been passed by reference, but why does the last statement print 1, 2
instead of 2, 2
?
In Python, like in many modern OO languages
foo = 1
actually creates an object with the value 1
and assigns a reference to the alias foo
. The internal type of foo is PyIntObject. This means Python isn't using the CPU / hardware int type, it always uses objects to handle numbers internally. The correct term is "plain integer", btw.
But creating objects is very expensive. That's why Python keeps an internal cache for a few numbers. Which means:
foo = 1
bar = 1
assert id(foo) == id(bar)
This isn't guaranteed, it's just a side effect of the implementation.
Number types in Python are also immutable. So even though bar
in your example is an alias for the cached int number, changing bar
doesn't modify the internal value. Instead, bar
is pointed to another instance which is why the id changes.
Because of the aforementioned optimization, this works as well:
foo = 1
bar = 1
assert id(foo) == id(bar)
bar += 1
assert id(foo) != id(bar)
bar -= 1
assert id(foo) == id(bar)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With