Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Are integers in Python passed by value or reference?

Tags:

python

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?

like image 880
ajay Avatar asked Jan 12 '23 03:01

ajay


1 Answers

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)
like image 197
Aaron Digulla Avatar answered Jan 22 '23 17:01

Aaron Digulla