Целочисленное кеширование для чисел больше 256 и меньше -5

Я знаю, что в 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

С логической точки зрения информация о том, что числа от -5 до 256 имеют одинаковые идентификаторы, ничего не говорит вам об идентификаторах целых чисел за пределами этого диапазона.

Eric Duminil 06.11.2018 09:22

Раньше, если вы проверяете ответы на этот вопрос, stackoverflow.com/questions/306313/… любое число больше, чем 256, раньше имело другой id

MaverickD 06.11.2018 09:23

@EricDuminil, означает ли это, что теперь python кэширует все возможные целые числа >= -5

MaverickD 06.11.2018 09:24

Невозможно воспроизвести на Python 3.6.3 (в последних двух примерах я получаю разные идентификаторы). То же самое для Python2. Вы уверены, что именно так вы это тестируете?

kabanus 06.11.2018 09:26

Я запускал его на PyCharm с помощью Python 3.6, также тестировал его на pythontutor.com

MaverickD 06.11.2018 09:28

Я думаю, что они запускают упаковку прогонов в функцию. Предлагаю вам добавить эту информацию к вопросу.

kabanus 06.11.2018 09:29

добавил подробности @kabanus

MaverickD 06.11.2018 09:31

Если вы помещаете их в функцию, компилятор байт-кода, вероятно, замечает, что две константы одинаковы, и выделяет только одну из них. Это не работает для -6, потому что - применяется к целому числу 6 во время выполнения.

torek 06.11.2018 09:32

@torek, Спасибо за комментарий. Я не вставлял его ни в какую функцию. просто работает прямо в pycharm. как я могу проверить, как pycharm вызывает это?

MaverickD 06.11.2018 09:37

Я не уверен, что сможешь. Кроме того, я тестировал с помощью dis.dis определение, которое устанавливает переменную в -5 и загружает -5 как константу, а не загружает 5 и вызывает -, так что эта теория в любом случае кажется ошибочной.

torek 06.11.2018 09:44
Почему в Python есть оператор "pass"?
Почему в Python есть оператор "pass"?
Оператор pass в Python - это простая концепция, которую могут быстро освоить даже новички без опыта программирования.
Некоторые методы, о которых вы не знали, что они существуют в Python
Некоторые методы, о которых вы не знали, что они существуют в Python
Python - самый известный и самый простой в изучении язык в наши дни. Имея широкий спектр применения в области машинного обучения, Data Science,...
Основы Python Часть I
Основы Python Часть I
Вы когда-нибудь задумывались, почему в программах на Python вы видите приведенный ниже код?
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
Алиса и Боб имеют неориентированный граф из n узлов и трех типов ребер:
Оптимизация кода с помощью тернарного оператора Python
Оптимизация кода с помощью тернарного оператора Python
И последнее, что мы хотели бы показать вам, прежде чем двигаться дальше, это
Советы по эффективной веб-разработке с помощью Python
Советы по эффективной веб-разработке с помощью Python
Как веб-разработчик, Python может стать мощным инструментом для создания эффективных и масштабируемых веб-приложений.
0
10
845
2

Ответы 2

На монетном дворе 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

Другие вопросы по теме