1

Input:

a=267
print(id(a))
b=267
print(id(b))

output:

1658953196976
1658953196976

Previous anwser give an reference to Python document: "The current implementation keeps an array of integer objects for all integers between -5 and 256, when you create an int in that range you actually just get back a reference to the existing object." However, for values outside that range and strings, individually created immutable objects with the same value always has the same id. So, why exactly do Python bother to "find" previous defined values when defining a new variable?

John Smith
  • 103
  • 1
  • 6
  • 1
    I can't reproduce. – Ch3steR Mar 26 '20 at 12:57
  • 2
    In a nutshell: you shouldn't think about this too hard, because it doesn't really mean anything. It depends on what Python flavour and version you're using. It might depend on whether you're in the REPL or not. It depends on variable scoping and the garbage collector. But most of all: **it's merely an internal optimisation and should have absolutely no influence on the behaviour of your code because you shouldn't be caring much about any object's `id`.** – deceze Mar 26 '20 at 13:01
  • 1
    @Ch3steR Compiled code can do more aggressive caching than the interactive interpreter, which "compiles" each line in isolation. – chepner Mar 26 '20 at 13:02
  • 1
    Make no assumption about what objects or references result from a literal, but with assignment involving two variables, like `a = b`, the language (and so all correct implementations) guarantees that `a is b` will be true until either name `a` or `b` is assigned to again. – chepner Mar 26 '20 at 13:12

2 Answers2

4

Looking up an object in a cache is cheaper than creating a new object. However, if you cached every int, you would be wasting memory on objects that only get used once. Further, the larger the cache, the more expensive any lookup might become.

The choice of the interval [-5, 256] is somewhat arbitrary, but based on observations that the cache size is small enough, and those values used frequently enough, to justify caching them on startup, rather than only caching them on demand.

In your example, though, the compiler can see, while compiling the code, that 267 is used twice, and so can choose to add it to the cache, independently of the numbers that are cached on startup, before any code is compiled.

I can reproduce the shared use of 267 if I put the code in a file and execute it. If I enter each line individually in the interactive interpreter, separate objects are created: when a = 267 is executed, it isn't yet known that another use of 267 will follow, and its value isn't cached. Putting both assignments on the same line, though, does let caching happen:

>>> a = 267
>>> print(id(a))
4325771792
>>> b = 267
>>> print(id(b))
4326331344
>>> a = 267; b=267
>>> print(id(a), id(b))
4326333264 4326333264
chepner
  • 497,756
  • 71
  • 530
  • 681
  • I should note that all of this is implementation dependent, so it could change even in a new release of CPython, but it seems reproducible enough for now :) PyPy, for instance, could (and I think does) do something different. – chepner Mar 26 '20 at 13:09
0

Both variables (names) point towards the same integer object in memory for the integers -5,256 because they are both small and are commonly used and so are loaded into memory before declaration.

>>> a = 1
>>> b = 1
>>> hex(id(a))
'0x7ffa7806e350'
>>> hex(id(b))
'0x7ffa7806e350'

This could also be tested using the 'is' operator.

>>> a is b
True

However, this caching of larger values outside of the range of -5,256 only occurs when defining both variables at the same time because the compiler is able to see that both are declared to be the same constant.

With caching:

>>> a = 333; b = 333
>>> hex(id(a))
'0x216de244790'
>>> hex(id(b))
'0x216de244790'
>>> a is b
True

Without caching:

>>> a = 333
>>> b = 333
>>> hex(id(a))
'0x216de2ac830'
>>> hex(id(b))
'0x216de244810'
>>> a is b
False

Note that this is specific to CPython and may not apply to all the other implementations of Python.

waffle
  • 1
  • 1