Две переменные в Python имеют одинаковый идентификатор, но не списки или кортежи

Две переменные в Python имеют одинаковые id:

a = 10
b = 10
a is b
>>> True

Если взять два list s:

a = [1, 2, 3]
b = [1, 2, 3]
a is b
>>> False

в соответствии с этой ссылкой Отправитель ответил, что ссылки на неизменяемые объекты имеют один и тот же идентификатор, а изменяемые объекты, такие как списки, имеют разные идентификаторы.

Итак, теперь, согласно его ответу, кортежи должны иметь одинаковые идентификаторы - значение:

a = (1, 2, 3)
b = (1, 2, 3)
a is b
>>> False

В идеале, поскольку кортежи не изменяются, он должен возвращать True, но он возвращает False!

Какое объяснение?

Ответ 1

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

Но есть некоторые исключения для небольших целых чисел (от -5 до 256) и небольших строк (интернированные строки со специальной длиной (обычно менее 20 символов)), которые являются одиночными и имеют одинаковый id (фактически один объект с несколькими указателями). Вы можете проверить этот факт следующим образом:

>>> 30 is 20 + 10
True
>>> 
>>> 300 is 200 + 100
False
>>> 'aa' * 2 is 'a' * 4
True
>>> 'aa' * 20 is 'a' * 40
False

И для настраиваемого объекта:

>>> class A:
...    pass
... 
>>> A() is A() # Every time you create an instance you'll have a new instance with new identity
False

Также обратите внимание, что оператор is проверяет идентификатор объекта, а не значение. Если вы хотите проверить значение, которое вы должны использовать ==:

>>> 300 == 3*100
True

И поскольку такого правила для кортежей (других типов) не существует, если вы определяете два одинаковых кортежа любого размера, они получат свои собственные идентификаторы:

>>> a = (1,)
>>> b = (1,)
>>>
>>> a is b
False

Обратите внимание, что факт одиночных целых чисел и интернированных строк верен, даже если вы определяете их в изменяемых и неизменяемых объектах:

>>> a = (100, 700, 400)
>>>
>>> b = (100, 700, 400)
>>>
>>> a[0] is b[0]
True
>>> a[1] is b[1]
False

Ответ 2

Неизменяемый != тот же объект. *

Постоянный объект - это просто объект, состояние которого не может быть изменено; и все. Когда новый объект будет создан, ему будет присвоен новый адрес. Таким образом, проверка того, совпадают ли адреса с is, вернет False.

То, что 1 is 1 или "a" is "a" возвращает True, связано с целым кэшированием и строкой interning, выполненный Python, поэтому не позволяйте ему смущать вас; это не связано с тем, что рассматриваемые объекты являются изменяемыми/неизменяемыми.


* Пустые неизменные объекты ссылаются на один и тот же объект, а их is ness возвращает true, это особый случай конкретной реализации.

Ответ 3

Взгляните на этот код:

>>> a = (1, 2, 3)
>>> b = (1, 2, 3)
>>> c = a
>>> id(a)
178153080L
>>> id(b)
178098040L
>>> id(c)
178153080L

Чтобы выяснить, почему a is c оценивается как True, тогда как a is b дает False, я настоятельно рекомендую вам поэтапно выполнить фрагмент выше в Интернет-преподаватель Python. Графическое представление объектов в памяти предоставит вам более глубокое понимание этой проблемы (я прилагаю скриншот).

введите описание изображения здесь