Я знаю, что в python есть концепция небольших целых чисел, которые являются числами от -5 до 256, и если две переменные присваивают одинаковые числа в этом диапазоне, они обе будут использовать один и тот же базовый объект.
Из документации Python,
#ifndef NSMALLPOSINTS
#define NSMALLPOSINTS 257
#endif
#ifndef NSMALLNEGINTS
#define NSMALLNEGINTS 5
#endif
/* Small integers are preallocated in this array so that they can be shared. The integers that are preallocated are those in the range -NSMALLNEGINTS (inclusive) to NSMALLPOSINTS (not inclusive). */
Также объяснено здесь,
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. So it should be possible to change the value of 1. I suspect the behaviour of Python in this case is undefined. :-)
Пример,
a = 255
b = 255
print(id(a))
print(id(b))
дает тот же идентификатор,
1561854394096
1561854394096
Что имеет смысл и также объясняется в этом ответе, Оператор "is" неожиданно ведет себя с целыми числами
Если два числа меньше -5, они также должны иметь разные идентификаторы, а именно:
a = -6
b = -6
print(id(a))
print(id(b))
дает,
2827426032208
2827426032272
пока это имеет смысл,
Но любое число больше, чем 256, должно иметь другой id,
Это должно вернуть разные идентификаторы,
a = 257
b = 257
print(id(a))
print(id(b))
Но это не так
2177675280112
2177675280112
Даже когда я использую очень большое целое число, идентификаторы одинаковы,
a = 2571299123876321621378
b = 2571299123876321621378
print(id(a))
print(id(b))
дает мне,
1956826139184
1956826139184
Может ли кто-нибудь сказать мне, почему числа больше 256 имеют одинаковые идентификаторы, хотя в коде Python диапазон от -5 до 257 (не включительно)
Обновлено:
Я пробовал использовать PyCharm как с Python 2.7, так и с 3.6. Также пробовал на PythonTutor.com
Раньше, если вы проверяете ответы на этот вопрос, stackoverflow.com/questions/306313/… любое число больше, чем 256, раньше имело другой id
@EricDuminil, означает ли это, что теперь python кэширует все возможные целые числа >= -5
Невозможно воспроизвести на Python 3.6.3 (в последних двух примерах я получаю разные идентификаторы). То же самое для Python2. Вы уверены, что именно так вы это тестируете?
Я запускал его на PyCharm с помощью Python 3.6, также тестировал его на pythontutor.com
Я думаю, что они запускают упаковку прогонов в функцию. Предлагаю вам добавить эту информацию к вопросу.
добавил подробности @kabanus
Если вы помещаете их в функцию, компилятор байт-кода, вероятно, замечает, что две константы одинаковы, и выделяет только одну из них. Это не работает для -6, потому что - применяется к целому числу 6 во время выполнения.
@torek, Спасибо за комментарий. Я не вставлял его ни в какую функцию. просто работает прямо в pycharm. как я могу проверить, как pycharm вызывает это?
Я не уверен, что сможешь. Кроме того, я тестировал с помощью dis.dis определение, которое устанавливает переменную в -5 и загружает -5 как константу, а не загружает 5 и вызывает -, так что эта теория в любом случае кажется ошибочной.






На монетном дворе Python 3.6.3 (тоже 2) воспроизвести не могу. Я предполагаю, что PyCharm или pythontutor оборачивают запуск во что-то перед интерпретацией - поскольку это не открытый код, мы не можем видеть внутренности, поэтому я не могу проверить. Причина, по которой я думаю, что это правда, - это while (все ниже - это мятный Python 3):
>>> x=2571299123876321621378
>>> y=2571299123876321621378
>>> print(id(x),id(y))
140671727739528 140671727739808
У вас может быть это:
>>> def bla():
... x=2571299123876321621378
... y=2571299123876321621378
... id(x)
... print(id(x),id(y))
...
>>> bla()
140671727742528 140671727742528
поэтому упаковка двух целых чисел во что-то, что интерпретатор может скомпилировать, допускает эти дополнительные оптимизации - например, использование одной и той же константы для обоих определений. Обратите внимание, что это тоже ограничено:
>>> def bla():
... x=2571299123876321621378
... y=2571299123876321621378
... print(id(x),id(y))
... x+=1
... y+=1
... print(id(x),id(y))
...
>>> bla()
140671727755592 140671727755592
140671728111088 140671728108808
У меня бы не было кода, который бы от этого никак не зависел - гарантия только от -5 до 256.
Эта проблема дублируется, ответил здесь
When you run code in a .py script, the entire file is compiled into a code object before executing it. In this case, CPython is able to make certain optimizations
С логической точки зрения информация о том, что числа от -5 до 256 имеют одинаковые идентификаторы, ничего не говорит вам об идентификаторах целых чисел за пределами этого диапазона.