1

Всем привет! Подскажите, почему оператор is ведет себя довольно странно, почему идентичность объектов равна False, тогда как по логике должна быть равна True. Почему так происходит? Объясните пожалуйста.

x = 1
y = x

print(x is y) # True

Но, если вызвать функцию id() которая вернет объекты типа int с одинковыми значениями становятся не идентичными:

print(id(x) is id(y)) # False

Здесь, по всей видимости возвращаются 2 разных объекта, но с одним и тем же значением, id объекта - 94232729371776. Если попытаться сравнить два других объекта типа int с одинаковым значением, то объекты идентичны:

a = 100
b = 100

print(a is b) # True

Почему в случае с функцией id, которая возвращает одно и тоже значение объекты разные? Как узнать какой объект (номер, id его) возвращает функция id?

  • Попробуйте то же самое с 256 и 257 :) – andreymal Oct 09 '17 at 06:48
  • 2
    Не нужно сравнивать id оператором is, это не имеет никакого смысла. – insolor Oct 09 '17 at 06:51
  • Со значениями 256 и 257 попробовал, is в обоих случаях возвращает True, для переменных a и b равным 256 и точно также для равных 257. – microcoder Oct 09 '17 at 06:56
  • 2
    В документации написано, что оператор is проверяет значения в переменных на то, что они являются одним объектом. Если вы знаете о ссылках, то знаете, что переменные ссылаются на область в памяти. В первом случае они ссылаются на одну и ту же область в памяти, во втором на разные области и считаются разными объектами. Поэтому как правило простые типы сравнивают оператором ==, а ссылочные через is. – Alex Krass Oct 09 '17 at 07:04
  • @dva, для равных по значению целых чисел is может давать как True, так и False. К примеру в текущих реализациях Python 256 is (255+1) == True, а для 257 is (256+1) == False. – insolor Oct 09 '17 at 07:12
  • @Alex Krass получается, что в runtime Пайтон не оптимизирует создание объектов, создает 2 разных объекта int с одним и тем же значением ID, а в случае парсинга, начальной стадии создания объектов в памяти при чтении исходников, Пайтон оптимизирует это, поэтому 'a' и 'b' переменные установленные в одно значение, в рантайме имеют один и тот же объект? А есть ли способ как то увидеть разность объектов по какому-то значению кроме оператора 'is' (функция id не годится уже)? – microcoder Oct 09 '17 at 07:13
  • @dva функция id годится, но сравнивать id нужно по равенству значений (==), а не по равенству объектов (is) – insolor Oct 09 '17 at 07:16
  • @insolor Понятно, т.е., тупо запомнить, что id ведет себя таким образом и использовать сравнение по значению, а не по ссылке. Спасибо. – microcoder Oct 09 '17 at 07:20
  • @dva, да, запомнить, но это не id ведет себя таким образом, а целые числа в Python. – insolor Oct 09 '17 at 07:20
  • @insolor, понятно, спасибо за уточнения! – microcoder Oct 09 '17 at 07:38

1 Answers1

4

Результат функции id() - это просто целое число.

В общем случае две числовые переменные являются двумя разными объектами, даже если их значения равны.

То есть само по себе выражение 1 is 1 в общем-то не должно возвращать True.

Но для некоторых числовых переменных (обычно либо не очень больших, либо больших, но явно присвоенных) интерпретатор в целях оптимизации может использовать один и тот же объект для разных числовых переменных, если их значения равны.

И для двух таких переменных сравнение через is действительно может возвращать True.

Это очень сильно зависит от конкретной реализации, поэтому не рекомендуется рассчитывать на то, что is по отношению к числам будет проявлять какое-то определённое поведение.

Конкретные значения нужно сравнивать только через == и !=. A is и is not стоит использовать только для сравнения с None или каких-то достаточно специфических случаев, когда важны не значения двух объектов, а действительно то, являются ли они одним и тем же объектом.

Xander
  • 20,499
  • Всё так, id возвращает целое число, но было не понятно, зачем в памяти создаются два разных объекта с одним и тем же значением и типом. Сейчас стало понятно, что "интерпретатор в целях оптимизации может использовать один и тот же объект для двух равных чисел", т.е., не обязан, а может, поэтому в моём случае с переменными 'a' и 'b' равными значению 100, он смог соптимизировать, а вот с функцией id() не смог или не захотел ))) Спасибо за разъяснение. – microcoder Oct 09 '17 at 07:35