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

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

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

Я объявил две переменные с именем x а также y присваивая одинаковые значения обеим переменным, но при использовании is оператор.

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

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

print x is y #It prints false!

10 ответов

Решение

Вы неправильно поняли, что 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 говорит вам, если два имени указывают на один и тот же объект. == говорит вам, если два имени относятся к объектам, которые имеют одинаковое значение.

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

>>> 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,

По аналогии с повторяющимся вопросом эта аналогия может сработать:

# - 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

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]

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, он возвращает истину, потому что == Операция только проверяет, имеют ли оба операнда одинаковое значение.

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

>>> 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
>>>

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

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
https://docs.python.org/2/reference/expressions.html

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

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

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

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

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

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 ) )

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

В is оператор - это не что иное, как английская версия ==. Поскольку идентификаторы двух списков разные, ответ неверен. Ты можешь попробовать:

a=[1,2,3]
b=a
print(b is a )#True

* Потому что идентификаторы обоих списков будут одинаковыми

Другие вопросы по тегам