Понимание оператора Python "есть"

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

Что это значит?

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

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

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

print x is y #It prints 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 для 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 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

Ответ 5

is и is not - два идентификационных оператора в Python. Оператор is не сравнивает значения переменных, а сравнивает тождества переменных. Рассмотрим это:

>>> a = [1,2,3]
>>> b = [1,2,3]
>>> hex(id(a))
'0x1079b1440'
>>> hex(id(b))
'0x107960878'
>>> a is b
False
>>> a == b
True
>>>

В приведенном выше примере показано, что идентификатор (также может быть адресом памяти в Cpython) отличается как для a, так и b (хотя их значения одинаковы). Вот почему, когда вы говорите a is b, он возвращает false из-за несоответствия в тождествах обоих операндов. Однако, когда вы говорите a == b, он возвращает true, потому что операция == проверяет, имеет ли оба операнда одно и то же значение, назначенное им.

Интересный пример (для дополнительного класса):

>>> del a
>>> del b
>>> a = 132
>>> b = 132
>>> hex(id(a))
'0x7faa2b609738'
>>> hex(id(b))
'0x7faa2b609738'
>>> a is b
True
>>> a == b
True
>>>

В приведенном выше примере, хотя a и b являются двумя разными переменными, a is b возвращается True. Это связано с тем, что тип a - это int, который является неизменным объектом. Таким образом, python (я думаю, чтобы сохранить память) выделил тот же объект в b, когда он был создан с тем же значением. Итак, в этом случае тождества согласованных переменных и a is b оказались True.

Это применимо ко всем неизменяемым объектам:

>>> del a
>>> del b
>>> a = "asd"
>>> b = "asd"
>>> hex(id(a))
'0x1079b05a8'
>>> hex(id(b))
'0x1079b05a8'
>>> a is b
True
>>> a == b
True
>>>

Надеюсь, что это поможет.

Ответ 6

Как вы можете проверить здесь на маленькие целые числа. Числа выше 257 не являются маленькими ints, поэтому он вычисляется как другой объект.

В этом случае лучше использовать ==.

Дополнительная информация здесь: http://docs.python.org/2/c-api/int.html

Ответ 7

x is y есть id(x) == id(y), сравнивая идентичность объектов.

Как отметил @tomasz-kurgan в комментарии ниже is оператор ведет себя необычно с определенными объектами.

Например

>>> class A(object):
...   def foo(self):
...     pass
... 
>>> a = A()
>>> a.foo is a.foo
False
>>> id(a.foo) == id(a.foo)
True

Ref;
https://docs.python.org/2/reference/expressions.html#is-not
https://docs.python.org/2/reference/expressions.html#id24

Ответ 8

X указывает на массив, Y указывает на другой массив. Эти массивы идентичны, но оператор is будет смотреть на те указатели, которые не идентичны.

Ответ 9

Он сравнивает идентификатор объекта, то есть, относятся ли переменные к одному и тому же объекту в памяти. Это похоже на == в Java или C (при сравнении указателей).

Ответ 10

Простой пример с фруктами

fruitlist = [" apple ", " banana ", " cherry ", " durian "]
newfruitlist = fruitlist
verynewfruitlist = fruitlist [:]
print ( fruitlist is newfruitlist )
print ( fruitlist is verynewfruitlist )
print ( newfruitlist is verynewfruitlist )

Выход:

True
False
False

Если вы попытаетесь

fruitlist = [" apple ", " banana ", " cherry ", " durian "]
newfruitlist = fruitlist
verynewfruitlist = fruitlist [:]
print ( fruitlist == newfruitlist )
print ( fruitlist == verynewfruitlist )
print ( newfruitlist == verynewfruitlist )

Выход отличается:

True
True
True

Это потому, что оператор == сравнивает только содержимое переменной. Для сравнения тождеств 2 переменных используйте оператор is

Чтобы распечатать идентификационный номер:

print ( id( variable ) )

Ответ 11

Я не нашел ответа на следующие вопросы:

a, b = 7, 7 a b дает True

но a, b = 777, 777 a is b дает False

Зачем?