Поговорим о небольших числах в CPython. Возьмем, например, два числа, 10 и 300:
>>> a = 10
>>> b = 300
>>> a is 10
True
>>> b is 300
False
Что?! Почему a указыввет на свое значение, а b y нет? Все дело в том, что интерпретатор хранит числа в диапазоне от - 5 до 256 в специальном массиве. Поэтому когда мы пишем
x = 10, то вообще-то получаем ссылку на объект, который уже существует в памяти:
>>> c = 1
>>> id(1)
94492411548416
>>> id(c)
94492411548416
Причем это касается любых значений, которые приводятся к целым числам этого диапазона. Можно завести число хоть в двоичном виде, хоть в hex, кеширование все равно будет работать:
>>> id(19)
94579033949504
>>> id(0b10011)
94579033949504
>>> id(0o23)
94579033949504
>>> id(0x13)
94579033949504
Числа вне диапазона - 5, 256 интерпретатор тоже будет пытаться оптимизировать, но только если они находятся в одной строке (или одном файле). В командной строке интерпретатора так не работает:
>>> d = 400
>>> d is 400
False
а так будет:
>>> e = 500; f = 500
>>> e is f
True
В общем и целом то, что нужно запомнить -- это что небольшие числа в интерпретаторе хранятся не так, как большие и что с ними следует пользоваться оператором ==, а не is. И это снова не фича, а деталь реализации для экономии ресурсов. 🐍