Приятно прочесть исходный код для Python2.7, который очень хорошо написан и понятен для чтения. (Я имею в виду версию 2.7.12, если вы хотите поиграть дома.) Хорошим местом для начала понимания кода является отличная серия лекций: C Python Internals, которая начинается с перспективы новичка.
Критический код (написанный на C), относящийся к нам, отображается в файле 'Objects/intobject.c' (я удалил некоторый код #ifdef и немного изменил создание нового объекта Integer для ясности):
По существу, он создает пресетный массив, содержащий все числа от -5 до 256 включительно и, если возможно, использует эти объекты (увеличивая количество ссылок на них с использованием макроса Py_INCREF). Если нет, он создаст новый объект PyInt_Type, который инициализируется с номером ссылки 1.
Тайна того, почему каждое число, похоже, имеет счетчик ссылок 3 (фактически практически любой новый объект), раскрывается только при просмотре байтового кода, который генерирует Python. Виртуальная машина работает со стеком значений (немного как в Forth), и каждый раз, когда объект помещается в стек значений, он увеличивает счетчик ссылок.
Так что я подозреваю, что ваш код сам предоставляет все 3 ссылки, которые вы видите, поскольку для чисел, не входящих в список небольших значений, вы должны получить уникальный объект. Первая ссылка, по-видимому, находится в стеке значений для вызывающего абонента getrefcount при его вызове; второй - в локальном списке переменных для кадра getrefcount; третий, вероятно, находится в стеке значений в кадре getrefcount, когда он просматривает свой счетчик ссылок.
Полезный инструмент, если вы хотите вникать в проблему, - это команда «компиляция» и команда «dis» (дизассемблировать), которая находится в модуле «dis», что вместе позволит вам прочитать фактическое байт-код, сгенерированный любым фрагментом кода Python, и должен помочь вам точно узнать, когда и где создается третья ссылка.
Что касается более высоких контрольных значений для небольших значений, то при запуске Python он автоматически загружает всю стандартную библиотеку и запускает довольно много кода инициализации модуля Python, прежде чем вы начнете интерпретировать свой собственный код. Эти модули содержат собственные копии многих небольших целых чисел (и объект None, который также уникален).
Попробуйте 'sys.getrefcount (257)', и это, вероятно, заметно снизится. –
Попробуйте 'sys.getrefcount (None)' для интересного номера. – cdarke
Это действительно странно, я никогда не создавал var с 257. Почему он возвращает 3? –