Why doesn't small integer caching seem to work with int objects from the round() function in Python 3?

Viewed 210

Can you please explain why this happens in Python v3.8?

a=round(2.3)
b=round(2.4)

print(a,b)
print(type(a),type(b))

print(a is b)
print(id(a))
print(id(b))

Output:

2 2
<class 'int'> <class 'int'>
False
2406701496848
2406701496656
>>>

2 is within the range of the small integer caching. So why are there different objects with the same value?

1 Answers

Looks like in 3.8, PyLong_FromDouble (which is what float.__round__ ultimately delegates to) explicitly allocates a new PyLong object and fills it in manually, without normalizing it (via the IS_SMALL_INT check and get_small_int cache lookup function), so it doesn't check the small int cache to resolve to the canonical value.

This will change in 3.9 as a result of issue 37986: Improve perfomance of PyLong_FromDouble(), which now has it delegate to PyLong_FromLong when the double is small enough to be losslessly represented as a C long. By side-effect, this will use the small int cache, as PyLong_FromLong reliably normalizes for small values.

Related