Добавить в корзинуПозвонить
Найти в Дзене

Почему у id(None) и id(print()) – один адрес, но id(print()) не равно None?

*** id(None) # 140705445104448 id(print()) # 140705445104448 id(print()) == None # False id(print()) is None # False Как видим, у id(None) и id(print()) – один адрес, но при этом id(print()) не равно None!.. Это одна из самых интересных и неочевидных особенностей языка Python, которая касается объекта None и его сравнения с другими объектами. *** 1) id(None) • В Python объект None является синглтоном (singleton). Это означает, что в рамках одного процесса (одной запущенной программы) существует только один-единственный экземпляр объекта None. • Всякий раз, когда мы запрашиваем None, то получаем ссылку на этот один и тот же объект в памяти. • Поэтому, когда мы вызываем id(None), то получаем адрес этого единственного объекта. *** 2) id(print()) • По умолчанию, если вызвать функцию print() без аргументов, она выведет символ новой строки (\n) в консоль (то есть пустую строку). • Результатом этого вызова является объект None (в Python любая функция, которая не возвращает з
Оглавление

***

Введём в интерактивном интерпретаторе Python следующий код:

id(None) # 140705445104448

id(print()) # 140705445104448

id(print()) == None # False

id(print()) is None # False

Как видим, у id(None) и id(print()) – один адрес, но при этом id(print()) не равно None!..

Это одна из самых интересных и неочевидных особенностей языка Python, которая касается объекта None и его сравнения с другими объектами.

***

Давайте разберём это по шагам.

1. Почему id(None) и id(print()) совпадают?

1) id(None)

В Python объект None является синглтоном (singleton). Это означает, что в рамках одного процесса (одной запущенной программы) существует только один-единственный экземпляр объекта None.

Всякий раз, когда мы запрашиваем None, то получаем ссылку на этот один и тот же объект в памяти.

Поэтому, когда мы вызываем id(None), то получаем адрес этого единственного объекта.

***

2) id(print())

По умолчанию, если вызвать функцию print() без аргументов, она выведет символ новой строки (\n) в консоль (то есть пустую строку).

-2

Результатом этого вызова является объект None (в Python любая функция, которая не возвращает значение явно, по умолчанию возвращает None).

Функция id() получает на вход этот результат, то есть объект None.

Таким образом, id(print()) вычисляет идентификатор не функции print, а объекта None, который является результатом её вызова.

Когда мы вызываем id(print()), мы сначала вызываем функцию (которая печатает пустую строку), а затем получаем адрес того же самого объекта None, который эта функция вернула.

С точки зрения идентификатора в памяти (id) – это один и тот же объект.

print(id(None)) и print(id(print())) выведут одно и то же число.

-3

***

2. Почему id(print()) == None и id(print()) is None возвращают False?

Здесь кроется главная ловушка. Мы сравниваем результат функции id() с объектом None.

Давайте посмотрим на типы данных:

• type(None) -> <class 'NoneType'>

• type(id(print())) -> <class 'int'>

-4

Функция id() по определению возвращает целое число (integer), представляющее адрес объекта в памяти.

***

Теперь разберём операторы сравнения:

1) Оператор is

Этот оператор проверяет идентичность объектов (ссылаются ли две переменные на один и тот же объект в памяти).

• id(print()) is None переводится как: "Является ли целое число (адрес) тем же самым объектом, что и объект None?".

Ответ: Нет. Это два совершенно разных типа объектов. Один – это число (например, 140705445104448), а другой – это специальный объект-заглушка (NoneType). Поэтому результат – False.

2) Оператор ==

Этот оператор проверяет на равенство значений.

В Python сравнение числа с объектом другого типа (например, int == NoneType) всегда возвращает False. Это сделано для того, чтобы избежать ошибок и неоднозначности.

Python не пытается привести число 140705445104448 к объекту None или наоборот. Он видит, что типы разные, и сразу говорит: "Эти значения не равны".

Поэтому результат – False.

***

Как проверить, что функция вернула None?

Чтобы проверить, что результат вызова функции равен None, нужно сравнивать именно результат вызова функции, а не его идентификатор.

Правильный способ проверки:

# Вариант 1: Проверка на идентичность (рекомендуется для None)

result = print()

print(result is None) # Выведет: True

# Вариант 2: Проверка на равенство (тоже сработает)

print(print() == None) # Выведет: True

# Вариант 3: Прямая проверка (самый частый случай)

if print() is None:

print("Функция ничего не вернула") # Выведет: Функция ничего не вернула

-5

Итог

• id(print()) == id(None) – это True, потому что обе функции возвращают идентификатор одного и того же единственного объекта None.

• id(print()) is None – это False, потому что мы сравниваем целое число (результат функции id) с объектом типа NoneType.

• print() is None – это True, потому что мы сравниваем результат вызова функции (который есть None) с самим объектом None.

***

Примечание

Встроенный текстовый dzen-редактор не позволяет сохранять отступы в публикуемом программном коде (отсутствие этих отступов в Python приведёт к ошибке!).