Понимание констант NSMALLPOSINTS и NSMALLNEGINTS

Как программисты, мы постоянно ищем способы оптимизировать наш код и сделать его более эффективным. Одним из методов, который может помочь нам в достижении этой цели, является объединение объектов в пул, которое позволяет сократить количество создаваемых объектов и объем используемой памяти за счет повторного использования одного объекта для представления нескольких значений.

Объединение объектов реализовано во многих языках программирования, включая реализацию Python на CPython, которая является наиболее широко используемым интерпретатором Python.

В этой статье будут объясняться основы интернирования объектов в CPython, которые вдохновлены одной из сложных задач в ALX и призваны предоставить всесторонний обзор объектов. объединение в CPython для моих коллег и других заинтересованных читателей. Давайте начнем …

Прежде всего, мы сосредоточимся конкретно на механизме объединения объектов для целых чисел в CPython, который реализован с использованием констант NSMALLPOSINTS и NSMALLNEGINTS. Эти константы определяют диапазон целочисленных значений, которые хранятся в пуле объектов, и они играют решающую роль в определении того, как пул объектов работает для целых чисел в CPython.

Оптимизация памяти

"Оптимизация заключается в поиске наилучшего решения, а не самого простого". — Неизвестно

Объединение объектов в CPython реализуется с помощью механизма, называемого «интернирование», который используется для уменьшения количества создаваемых объектов и объема используемой памяти за счет повторного использования одного объекта для представления нескольких значений. . Интернирование используется в основном для неизменяемых объектов, таких как строки, но также используется для некоторых других типов объектов, таких как целые числа и кортежи.

В CPython интернирование реализовано с использованием механизма интернирования строк, что означает, что один строковый объект используется для представления нескольких строковых литералов с одинаковым значением. Когда интерпретатор Python встречает строковый литерал, он проверяет, существует ли объект с таким же значением во внутреннем пуле. Если это так, интерпретатор возвращает ссылку на существующий объект, а не создает новый объект.

Для целых чисел объединение объектов в CPython реализуется с помощью констант NSMALLPOSINTS и NSMALLNEGINTS, которые определяют диапазон целочисленных значений, хранящихся в пуле объектов (обычно это массив из 262 целых чисел). Эти константы используются для определения необходимости создания нового объекта int или использования существующего объекта из пула объектов. Это структурирование в основном используется для быстрого доступа к этим целым числам.

Константы NSMALLPOSINTS и NSMALLNEGINTS

Константа NSMALLPOSINTS представляет диапазон положительных целых чисел, хранящихся в пуле объектов, а константа NSMALLNEGINTS представляет диапазон отрицательных целых чисел, хранящихся в пуле объектов.

В CPython реализации Python3 с параметрами/конфигурацией по умолчанию NSMALLPOSINTS равно 256, а NSMALLNEGINTS равно 5, что означает, что пул объектов содержит целочисленные объекты со значениями от -5 до 256.

#define NSMALLPOSINTS           257
#define NSMALLNEGINTS           5

Это означает, что когда вы создаете объект int со значением, находящимся в этом диапазоне, интерпретатор Python не будет создавать новый объект, а вместо этого вернет ссылку на существующий объект, хранящийся в пуле объектов.

Вот несколько примеров того, как объединение объектов используется для целых чисел в CPython реализации Python:

ПРИМЕЧАНИЕ. Операторisсравнивает идентификаторы (или области памяти) двух объектов и возвращает значение True, если они совпадают.

  • Объединение объектов для положительных целых чисел:
>>> NSMALLPOSINTS = 256
>>> a = 99
>>> b = 99
>>> a is b
True

В этом примере для константы NSMALLPOSINTS установлено значение 256, что означает, что все положительные целые числа в диапазоне от 1 до 256 хранятся в пуле объектов. Когда переменным a и b присваивается значение 99, интерпретатор Python возвращает ссылку на один и тот же объект из пула объектов для обеих переменных, а не создает новый объект. Вот почему оператор is возвращает True при сравнении a и b.

  • Объединение объектов для отрицательных целых чисел:
>>> NSMALLNEGINTS = 5
>>> c = -2
>>> d = -2
>>> c is d
True

В этом примере константе NSMALLNEGINTS присвоено значение 5, что означает, что все отрицательные целые числа в диапазоне от -5 до -1 сохраняются в пуле объектов. Когда переменным c и d присваивается значение -2, интерпретатор Python возвращает ссылку на один и тот же объект из пула объектов для обеих переменных, а не создает новый объект. Вот почему оператор is возвращает True при сравнении c и d.

  • Объединение объектов для целых чисел вне диапазона, определенногоNSMALLPOSINTSиNSMALLNEGINTS:
>>> a = 257
>>> b = 257
>>> a is b
False

В этом примере переменным a и b присваивается значение 257, которое выходит за пределы диапазона, определенного константой NSMALLPOSINTS. В результате интерпретатор Python создает новый объект int для каждой переменной, а не возвращает ссылку на существующий объект из пула объектов. Вот почему оператор is возвращает False при сравнении a и b.

И, наконец, хитрый вопрос:

>>> print("I")
>>> print("Love")
>>> print("Python")

С этими строками кода и при условии, что мы используем реализацию Python3 на CPython с параметрами/конфигурацией по умолчанию. До выполнения строки 2 (print("Love")) сколько объектов int было создано и все еще находится в памяти?

Надеюсь, вы угадали правильно :), правильный ответ будет 262. Хотите знать, почему?

Ну, так как вопрос спрашивает, сколько объектов int было создано и все еще находится в памяти, тогда как строковый литерал "I" не является объектом int, а функция print() не создает никаких объектов int. Поэтому выполнение первой строки скрипта print("I") не создает никаких новых объектов int. Но в памяти есть существующий объект, представляющий собой массив из 262 целых чисел (257 + 5), отсюда и ответ.

Почему это важно?

Объединение объектов в пул — это метод оптимизации, который используется для уменьшения количества создаваемых объектов и объема используемой памяти за счет повторного использования одного объекта для представления нескольких значений. Это может повысить производительность программы Python за счет сокращения накладных расходов на создание и уничтожение объектов.

Как бы хорошо это ни казалось, также важно отметить, что объединение объектов — это лишь один из многих методов оптимизации, и есть много других ресурсов, доступных для тех, кто хочет узнать больше об оптимизации в Python. Некоторое возможное дополнительное чтение по этой теме включает официальную документацию Python по оптимизации производительности, а также статьи и учебные пособия по таким темам, как интернирование объектов и сборка мусора — если вам нужна дополнительная информация, я дам ссылки на несколько ресурсов ниже.

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

Удачного кодирования!

Ресурсы 🔗

Чтобы читать больше таких интересных статей о Python и науке о данных, подпишитесь на мой блог https://bolexzy.hashnode.dev/ . Вы также можете связаться со мной в LinkedIn.