Сравните, ссылаются ли две переменные на один и тот же объект в Python

94

Как проверить, ссылаются ли две переменные на один и тот же объект?

x = ['a', 'b', 'c']
y = x                 # x and y reference the same object
z = ['a', 'b', 'c']   # x and z reference different objects
pic11
источник
2
возможный дубликат Как проверить, ссылаются ли две переменные на один и тот же объект в Python?
Чиро Сантилли 郝海东 冠状 病 六四 事件 法轮功

Ответы:

134

Вот для чего is: x is yвозвращает, Trueесли xи yявляются одним и тем же объектом.

Йохен Ритцель
источник
6
В этом примере x is zвозвращается False. Но если x и z присваиваются одинаковые значения вместо списков (например x, z = 13, 13), x is zвозвращается True. Почему это?
Билл
12
@Bill: Это артефакт того, как Python обрабатывает целые числа. Python выделяет целое число объектов , к которым xи zточке. Поскольку маленькие целые числа являются обычным явлением (-1 как значение ошибки, 0 каждый раз, когда вы действительно что-то индексируете, маленькие числа обычно являются разумными значениями по умолчанию) Python оптимизирует, предварительно выделяя маленькие числа (от -5 до 256) и повторно используя один и тот же целочисленный объект. Таким образом, ваш пример работает только для чисел в этом диапазоне. Попробуйте назначить что - то большее, то есть 270. Для получения дополнительной информации смотрите здесь
ted
1
@AndresR Нет, это неправильно. isпроверяет, ссылаются ли два имени на одну и ту же ячейку памяти. Это не имеет ничего общего с самим объектом. Легко иметь неизменяемые объекты, такие как строки, которые равны, но не хранятся в одном и том же месте, например ''a'*10000 is 'a' * 10000False.
Йохен Ритцель
1
@JochenRitzel Вы совершенно правы, спасибо за этот комментарий! Итак, я не понимаю, что происходит "af" is "af"или () is ()... почему они используют одну и ту же ячейку памяти?
AndresR
2
@AndreasR Для буквальных строк / чисел в коде компилятор проверяет, существуют ли они только один раз, и повторно использует их. Специальные значения, такие как (), None, True, False и т. Д., Также определены как одиночные. Во время выполнения среда выполнения также пытается повторно использовать небольшие числа и строки, но в конечном итоге это компромисс между скоростью и памятью, и то, что происходит, зависит от того, как была реализована среда выполнения Python.
Йохен Ритцель
12

y is xбудет True, y is zбудет False.

Марк Рушаков
источник
11

Вы также можете использовать id (), чтобы проверить, к какому уникальному объекту относится каждое имя переменной.

In [1]: x1, x2 = 'foo', 'foo'

In [2]: x1 == x2
Out[2]: True

In [3]: id(x1), id(x2)
Out[3]: (4509849040, 4509849040)

In [4]: x2 = 'foobar'[0:3]

In [5]: x2
Out[5]: 'foo'

In [6]: x1 == x2
Out[6]: True

In [7]: x1 is x2
Out[7]: False

In [8]: id(x1), id(x2)
Out[8]: (4509849040, 4526514944)
Билл
источник
Замечание @ted об использовании id здесь весьма актуально.
Лев Уфимцев
11

В то время как два правильных решений x is zи id(x) == id(z)уже отвечал, я хочу отметить деталь реализации питона. Python хранит целые числа как объекты, в качестве оптимизации он генерирует кучу небольших целых чисел в начале (от -5 до 256) и указывает КАЖДУЮ переменную, содержащую целое число с небольшим значением, на эти предварительно инициализированные объекты. Больше информации

Это означает, что для целочисленных объектов, инициализированных одними и теми же небольшими числами (от -5 до 256), проверка идентичности двух объектов вернет истину ( ON C-Pyhon , насколько мне известно, это деталь реализации ), а для более крупных числа это возвращает истину, только если один объект инициализирован из другого.

> i = 13
> j = 13
> i is j
True

> a = 280
> b = 280
> a is b
False

> a = b
> a
280
> a is b
True
Тед
источник
python3.6: а = 98765; b = 98765; a равно b => верно. Что-то, видимо, изменилось.
Михаил Калашников
@MikhailKalashnikov Неа. Я тестировал Python 3.6.2, он все еще существует.
nix
все еще существует на python 3.7.7
Билл Хуанг
2

Мне очень нравится визуальная обратная связь, поэтому я иногда просто открываю http://www.pythontutor.com/visualize.html#mode=edit, чтобы увидеть, как распределяется память и что на что ссылается.

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

Добавил эту потрясающую гифку, так как этот ответ о визуализации ..

user1767754
источник
2

Это взято с сайта docs.python.org: «Каждый объект имеет идентификатор, тип и значение. Идентификатор объекта никогда не изменяется после его создания; вы можете думать об этом как об адресе объекта в памяти. Оператор« есть » сравнивает идентичность двух объектов; функция id () возвращает целое число, представляющее его идентичность ".

По-видимому, каждый раз, когда вы меняете значение, объект воссоздается, на что указывает изменение идентификатора. Строка x = 3, за которой следует строка x = 3.14, не дает ошибок и дает разные идентификаторы, типы и значения для x.

Скотт Вудс
источник
1
Отличный документальный улов.
прости
xэто имя идентификации объекта с значением из 3, а не как объект сам по себе. Когда вы это сделали x=3.14, вы не изменили объект, который ранее был идентифицирован x- вы изменили объект, к которому относится имя x .
ArtOfWarfare