Вопрос-Ответ

Understanding the "is" operator [duplicate]

Понимание оператора "is"

Оператор is соответствует не значениям переменных, а самим экземплярам.


Что это на самом деле означает?

Я объявил две переменные с именами x и y, присвоив обеим переменным одинаковые значения, но это возвращает false, когда я использую is оператор.

Мне нужно разъяснение. Вот мой код:

x = [1, 2, 3]
y = [1, 2, 3]

print(x is y) # False
Переведено автоматически
Ответ 1

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

Из документации к is оператору:


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


Вместо этого используйте оператор ==:

print(x == y)

Это выводит True. x и y - это два отдельных списка:

x[0] = 4
print(y) # prints [1, 2, 3]
print(x == y) # prints False

Если вы используете id() функцию, вы увидите, что x и y имеют разные идентификаторы:

>>> id(x)
4401064560
>>> id(y)
4401098192

но если бы вы назначили y to x, то оба указывали бы на один и тот же объект:

>>> x = y
>>> id(x)
4401064560
>>> id(y)
4401064560
>>> x is y
True

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

Помните, что в Python имена - это просто метки, ссылающиеся на значения; у вас может быть несколько имен, указывающих на один и тот же объект. is сообщает, указывают ли два имени на один и тот же объект. == сообщает, относятся ли два имени к объектам, имеющим одинаковое значение.

Ответ 2

Другой дубликат спрашивал, почему две равные строки обычно не идентичны, на что здесь на самом деле нет ответа:

>>> x = 'a' 
>>> x += 'bc'
>>> y = 'abc'
>>> x == y
True
>>> x is y
False

Итак, почему это не одна и та же строка? Особенно учитывая это:

>>> z = 'abc'
>>> w = 'abc'
>>> z is w
True

Давайте ненадолго отложим вторую часть. Как первая может быть правдой?

Интерпретатор должен был бы иметь "таблицу интернирования", таблицу, сопоставляющую строковые значения строковым объектам, поэтому каждый раз, когда вы пытаетесь создать новую строку с содержимым 'abc', вы получаете обратно тот же объект. ВВикипедии есть более подробное обсуждение того, как работает интернирование.

В Python есть таблица интернирования строк; вы можете вручную интернировать строки с помощью sys.intern метода.

Фактически, Python разрешено автоматически вставлять любые неизменяемые типы, но это не требуется для этого. Разные реализации будут вставлять разные значения.

CPython (реализация, которую вы используете, если вы не знаете, какую реализацию используете) автоматически обрабатывает небольшие целые числа и некоторые специальные синглтоны, такие как False, но не строки (или большие целые числа, или маленькие кортежи, или что-либо еще). Вы можете увидеть это довольно легко:

>>> a = 0
>>> a += 1
>>> b = 1
>>> a is b
True
>>> a = False
>>> a = not a
>>> b = True
a is b
True
>>> a = 1000
>>> a += 1
>>> b = 1001
>>> a is b
False

Хорошо, но почему были z и w идентичны?

Это не интерпретатор, автоматически интернирующий значения, это компилятор, сворачивающий значения.

Если одна и та же строка во время компиляции появляется дважды в одном и том же модуле (что именно это означает, определить сложно - это не то же самое, что строковый литерал, потому что r'abc', 'abc', и 'a' 'b' 'c' — это все разные литералы, но одна и та же строка, но ее легко понять интуитивно), компилятор создаст только один экземпляр строки с двумя ссылками.

Фактически, компилятор может пойти еще дальше: 'ab' + 'c' может быть преобразован в 'abc' оптимизатором, и в этом случае он может быть свернут вместе с 'abc' константой в том же модуле.

Опять же, это то, что Python разрешено, но не обязательно делать. Но в этом случае CPython всегда сворачивает небольшие строки (а также, например, небольшие кортежи). (Хотя пошаговый компилятор интерактивного интерпретатора не выполняет ту же оптимизацию, что и модульный компилятор, поэтому вы не увидите точно таких же результатов в интерактивном режиме.)


Итак, что вы должны делать по этому поводу как программист?

Ну ... ничего. У вас почти никогда не бывает причин беспокоиться о том, идентичны ли два неизменяемых значения. Если вы хотите знать, когда можно использовать a is b вместо a == b, вы задаете неправильный вопрос. Просто всегда используйте a == b, за исключением двух случаев:


  • Для более удобочитаемых сравнений с одноэлементными значениями , такими как x is None.

  • Для изменяемых значений, когда вам нужно знать, x повлияет ли изменение на y.

Ответ 3

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

>>> x = [1, 2, 3]
>>> y = [1, 2, 3]
>>> print x is y
False
>>> z = y
>>> print y is z
True
>>> print x is z
False
>>> y[0] = 5
>>> print z
[5, 2, 3]
Ответ 4

Эта аналогия, вызванная повторяющимся вопросом, может сработать:

# - Darling, I want some pudding!
# - There is some in the fridge.

pudding_to_eat = fridge_pudding
pudding_to_eat is fridge_pudding
# => True

# - Honey, what's with all the dirty dishes?
# - I wanted to eat pudding so I made some. Sorry about the mess, Darling.
# - But there was already some in the fridge.

pudding_to_eat = make_pudding(ingredients)
pudding_to_eat is fridge_pudding
# => False
python