Как реализовано ключевое слово «is» в Python? - PullRequest
58 голосов
/ 07 июня 2010

... ключевое слово is, которое можно использовать для равенства в строках.

>>> s = 'str'
>>> s is 'str'
True
>>> s is 'st'
False

Я пробовал оба __is__() и __eq__(), но они не работали.

>>> class MyString:
...   def __init__(self):
...     self.s = 'string'
...   def __is__(self, s):
...     return self.s == s
...
>>>
>>>
>>> m = MyString()
>>> m is 'ss'
False
>>> m is 'string' # <--- Expected to work
False
>>>
>>> class MyString:
...   def __init__(self):
...     self.s = 'string'
...   def __eq__(self, s):
...     return self.s == s
...
>>>
>>> m = MyString()
>>> m is 'ss'
False
>>> m is 'string' # <--- Expected to work, but again failed
False
>>>

Ответы [ 10 ]

121 голосов
/ 07 июня 2010

Проверка строк с is работает только тогда, когда строки интернированы.Если вы действительно не знаете, что делаете, и явно интернированы строки, которые вы должны никогда не использовать is для строк

is тесты на идентичность , а не равенство .Это означает, что Python просто сравнивает адрес памяти, в котором находится объект. is в основном отвечает на вопрос "Есть ли у меня два имени для одного и того же объекта?"- перегрузка, которая не имеет смысла.

Например, ("a" * 100) is ("a" * 100) - это False .Обычно Python записывает каждую строку в другое место в памяти, интернирование в основном происходит для строковых литералов.

20 голосов
/ 07 июня 2010

Оператор is эквивалентен сравнению значений id(x).id в настоящее время реализовано для использования указателей в качестве сравнения.Таким образом, вы не можете перегружать is сам по себе, и AFAIK вы не можете перегружать id.Необычный в питоне, но он есть.

16 голосов
/ 07 июня 2010

Ключевое слово Python is проверяет идентичность объекта.Вы не должны использовать его для проверки на равенство строк.Может показаться, что это часто работает, потому что реализации Python, как и во многих языках очень высокого уровня, выполняют «интернирование» строк.То есть строковые литералы и значения внутренне хранятся в хешированном списке, а идентичные идентифицируются как ссылки на один и тот же объект.(Это возможно, потому что строки Python являются неизменяемыми).

Однако, как и в случае с любыми деталями реализации, вам не следует полагаться на это.Если вы хотите проверить на равенство, используйте оператор ==.Если вы действительно хотите проверить идентичность объекта, используйте is ---, и мне будет сложно найти случай, когда вам следует позаботиться об идентичности строкового объекта.К сожалению, вы не можете рассчитывать на то, что две строки как-то «намеренно» идентичны объектным ссылкам из-за вышеупомянутого интернирования.

8 голосов
/ 07 июня 2010

Ключевое слово is сравнивает объекты (или, скорее, сравнивает, если две ссылки относятся к одному и тому же объекту).

Вот почему, я думаю, нет механизма для обеспечения собственной реализации.

Это иногда работает с строками, потому что Python хранит строки «умно», так что при создании двух одинаковых строк они хранятся в одном объекте.

>>> a = "string"
>>> b = "string"
>>> a is b
True
>>> c = "str"+"ing"
>>> a is c
True

Можно надеяться, что вы можете увидеть сравнение с данными в простом примере с копией:

>>> a = {"a":1}
>>> b = a
>>> c = a.copy()
>>> a is b
True
>>> a is c
False
5 голосов
/ 12 октября 2010

Если вы не боитесь испортить байт-код, вы можете перехватить и пропатчить COMPARE_OP с помощью аргумента 8 ("is"), чтобы вызвать функцию хука для сравниваемых объектов. Посмотрите dis документацию модуля для запуска.

И не забудьте также перехватить __builtin__.id(), если кто-то сделает id(a) == id(b) вместо a is b.

2 голосов
/ 09 марта 2017

'is' сравнивает идентичность объекта, тогда как == сравнивает значения.

Пример:

a=[1,2]
b=[1,2]
#a==b returns True
#a is b returns False

p=q=[1,2]
#p==q returns True
#p is q returns True
2 голосов
/ 07 апреля 2011

не может сравнивать строковую переменную со строковым значением и двумя строковыми переменными, когда строка начинается с '-'. Моя версия Python 2.6.6

>>> s = '-hi'
>>> s is '-hi'
False 
>>> s = '-hi'
>>> k = '-hi'
>>> s is k 
False
>>> '-hi' is '-hi'
True
1 голос
/ 04 января 2013

Вы используете сравнение личности. == это, вероятно, то, что вы хотите.Исключением является случай, когда вы хотите проверить, являются ли один и тот же элемент ТОЧНЫМ и тем же объектом и в одной и той же позиции памяти.В ваших примерах элементы не совпадают, так как один имеет другой тип (my_string), чем другой (строка).Кроме того, в python нет такого понятия, как someclass. __is__ (если, конечно, вы сами его туда не поместите).Если бы было, сравнивать объекты с - это , то было бы ненадежным просто сравнивать места в памяти.

Когда я впервые столкнулся с ключевым словом is , меня это смутилоЧто ж.Я бы подумал, что это и == ничем не отличаются.Они создали одинаковый вывод интерпретатора для многих объектов.Этот тип предположения на самом деле именно то, для чего является ... для.Это эквивалент Python «Эй, не путайте эти два объекта. Они разные», что по сути и было то, что [кто бы это ни выправил меня] сказал.Написано очень по-разному, но одна точка == другая точка.

для некоторых полезных примеров и некоторого текста, чтобы помочь с иногда запутанными различиями, посетите документ с почтового хоста python.org написанныйот "Danny Yoo"

или, если он не в сети, используйте незарегистрированный пастин , который я сделал из его тела.

на случай, если они, примерно в 20 или более синих лунах(синие луны - это настоящее событие), оба не работают, я приведу примеры кода

###
>>> my_name = "danny"
>>> your_name = "ian"
>>> my_name == your_name
0                #or False
###

###
>>> my_name[1:3] == your_name[1:3]
1    #or True
###

###
>>> my_name[1:3] is your_name[1:3]
0
###
1 голос
/ 15 июня 2011

Вы не можете перегрузить оператор is. То, что вы хотите перегрузить, это оператор ==. Это можно сделать, определив метод __eq__ в классе.

0 голосов
/ 07 февраля 2017

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

>>> a == b

будет оцениваться в

True

Но если

>>> a is b

оценивается в

False

, вывероятно, следует проверить

>>> type(a)

и

>>> type(b)

Они могут отличаться и стать причиной сбоя.

...