wtfpython icon indicating copy to clipboard operation
wtfpython copied to clipboard

Interned/cached integer in a function

Open frenzymadness opened this issue 3 years ago • 4 comments

Code example:

>>> def a(b=3000):
...    return b is 3000
[...]
>>> a()
True
>>> a(b=3000)
False

From this article: https://utcc.utoronto.ca/~cks/space/blog/python/PythonIsWithLiteral

frenzymadness avatar Feb 22 '21 10:02 frenzymadness

Thanks @frenzymadness

Both the examples you shared (this one and #257) are very interesting. I'll add them in the next revision (unless someone else wants to raise a PR :)

satwikkansal avatar Feb 22 '21 11:02 satwikkansal

You can do it more easily:

a = 1111
assert a + 1 == 1112  # True
assert a + 1 is 1112  # False

The key point here is to take a large enough number that it won't be cached by Python.

a = 1
asert a + 1 == 2  # True
assert a + 1 is 1  # True

david-shiko avatar Jan 08 '23 20:01 david-shiko

@david-shiko I'm not sure I understand your point. What you described is already here and the interned numbers are from -5 to 256 for CPython.

My example here is about the default value for kw argument. It shows that even a number much higher than 256 mentioned above can be cached in some cases.

frenzymadness avatar Jan 09 '23 07:01 frenzymadness

It seems that the Python interpreter uses cached numeric literals on a per-compile basis.

>>> def a(b=3000):
...     c = 3000
...     print(id(b), id(c), b is c)
...
>>> a()
140032012726032 140032012726032 True
>>> a(3000)
140032012726192 140032012726032 False
>>> b = 3000
>>> c = 3000
>>> print(id(b), id(c), b is c)
140032012726192 140032012726160 False

If you make it into a script file and run it, the whole thing will compile and everything will be True.

def a(b=3000):
    c = 3000
    print(id(b), id(c), b is c)

a()
a(3000)
b = 3000
c = 3000
print(id(b), id(c), b is c)
139979290826992 139979290826992 True
139979290826992 139979290826992 True
139979290826992 139979290826992 True

shiracamus avatar Jan 10 '23 01:01 shiracamus