Оператор «есть» не работает с объектами с одинаковым идентификатором

Я бегу:

Python 2.7.8 (default, Oct  6 2017, 09:25:50)
GCC 4.1.2 20070626 (Red Hat 4.1.2-14) on Linux 2

Согласно документации:

Операторы is и is not проверяют идентификацию объекта: x is y равно True тогда и только тогда, когда x и y являются одним и тем же объектом.

Чтобы получить идентификацию объекта, мы можем использовать id функция.


Если мы откроем новый REPL, мы увидим, что 300 и -6 имеют одинаковую идентичность (на CPython, это означает, что оба ссылаются на один и тот же адрес памяти):

>>> id(300)
94766593705400
>>> id(-6)
94766593705400

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

Однако выполнение 300 is -6 дает False:

>>> 300 is -6
False

У меня есть пара вопросов:

  • Почему (и как) 300 и -6 имеют один и тот же идентификатор?
  • Если да, то почему 300 is -6 уступает False?

person Matias Cicero    schedule 20.12.2017    source источник
comment
REPL повторно использует IDs. Попробуйте это, и вы поймете: print(id(300)) or print(id(-6)) or 300 is -6   -  person cs95    schedule 20.12.2017
comment
Невозможно воспроизвести в Python 3 в Windows Python 3.4.2 (v3.4.2:ab2c023a9432, Oct 6 2014, 22:15:05) [MSC v.1600 32 bit (Intel)] on win32 Type "help", "copyright", "credits" or "license" for more information. >>> id(300) 7807344 >>> id(-6) 8757184 >>> id(300) 8757184 >>> id(-6) 8755376   -  person DeepSpace    schedule 20.12.2017
comment
Однако он воспроизводится в Python 2 на Centos Python 2.6.6 (r266:84292, Sep 11 2012, 08:34:23) [GCC 4.4.6 20120305 (Red Hat 4.4.6-4)] on linux2 Type "help", "copyright", "credits" or "license" for more information. >>> id(300) 15912616 >>> id(-6) 15912616 >>> id(300) 15912616   -  person DeepSpace    schedule 20.12.2017
comment
@cᴏʟᴅsᴘᴇᴇᴅ У вас случайно нет источника, подтверждающего это?   -  person Matias Cicero    schedule 20.12.2017
comment
На самом деле это упоминается в документах... Два объекта с не- перекрывающиеся времена жизни могут иметь одинаковое значение id().   -  person cs95    schedule 20.12.2017
comment
@cᴏʟᴅsᴘᴇᴇᴅ Спасибо! Теперь это имеет смысл   -  person Matias Cicero    schedule 20.12.2017
comment
Также стоит отметить, что Python кэширует целые числа в диапазоне [-5, 256]: >>> 6 is 6 True >>> -999 is -999 False   -  person DeepSpace    schedule 20.12.2017


Ответы (2)


После выполнения id(300) ссылки на 300 больше не существуют, поэтому идентификатор освобождается. Когда вы выполняете id(6), он получает тот же кусок памяти и вместо этого сохраняет 6. Когда вы делаете -300 is 6, -300 и 6 ссылаются одновременно, поэтому у них больше не будет одного и того же адреса.

Если вы сохраняете ссылки и на -300, и на 6, происходит следующее:

>>> a, b = -300, 6
>>> id(a)
some number
>>> id(b)
some different number; 6 is still in the other memory address.

Примечание. В CPython числа от -5 до 256 (я думаю) кэшируются и всегда будут иметь один и тот же адрес, поэтому этого не произойдет.

person internet_user    schedule 20.12.2017
comment
Я только что проверил то, что вы сказали. Это имеет смысл - person Matias Cicero; 20.12.2017
comment
Я бы использовал другой пример, а не 6, так как он находится в диапазоне целых чисел, которые Python все равно кэширует (от -5 до 256): >>> 6 is 6 True >>> -999 is -999 False - person DeepSpace; 20.12.2017
comment
@DeepSpace Хороший улов! Редактирование. - person internet_user; 20.12.2017

Это задокументированное поведение функции id():

Возвращает «идентификатор» объекта. Это целое (или длинное целое), которое гарантированно будет уникальным и постоянным для данного объекта в течение всего времени его жизни. Два объекта с непересекающимися сроками жизни могут иметь одинаковое значение id().

Время жизни целочисленного объекта в примере кода — это просто вызов функции (например, id(300)), так как других ссылок на него не существует.

person Eugene Yarmash    schedule 20.12.2017
comment
Я не мог понять это утверждение в то время, но теперь я понимаю! - person Matias Cicero; 20.12.2017