Основываясь на нескольких предложениях на разных форумах и экспериментируя со стандартной библиотекой, чтобы соответствовать критериям, мой текущий вывод заключается в том, что это невозможно сделать с библиотекой и типами, которые у нас в настоящее время есть.
Это побочная заметка, но в идиоматическом питоне вы часто увидите такие вещи, как:
if x is None:
# some clauses
Это безопасно, потому что гарантированно будет один экземпляр объекта Null (т. е. None) .
is
- тестирование идентичности, ==
- тестирование равенства (см. Документация Python ).
В большинстве случаев, если a is b
, то a == b
. Но есть исключения, например:
>>> nan = float('nan')
>>> nan is nan
True
>>> nan == nan
False
Таким образом, вы можете использовать is
для тестирования идентичности, никогда не проводить тесты равенства.
Другие ответы здесь верны: is
используется для сравнения identity , а ==
используется для сравнения равенство . Поскольку вам нужно заботиться о равенстве (две строки должны содержать одни и те же символы), в этом случае оператор is
просто ошибочен, и вы должны использовать вместо него ==
.
Причина is
работает интерактивно, что (большинство) строковых литералов по умолчанию interned . Из Wikipedia:
Интернированные строки ускоряют сопоставления строк, которые иногда являются узким местом производительности в приложениях (например, компиляторами и языками динамического программирования), которые в значительной степени зависят от хэш-таблиц со строковыми ключами. Без интернирования проверка того, что две разные строки равны, включает в себя изучение каждого символа обеих строк. Это медленно по нескольким причинам: по своей сути это O (n) в длине строк; обычно требуется чтение из нескольких областей памяти, которые требуют времени; и чтение считывает кеш процессора, что означает, что для других нужд меньше кеша. С интернированными строками после первоначальной статической операции достаточно простого теста на идентификацию объекта; это обычно реализуется как тест равенства указателя, обычно это всего лишь одна машинная команда без ссылки на память.
blockquote>Итак, когда у вас есть два строковых литерала (слова, которые буквально введены в ваш исходный код программы, окруженный кавычками) в вашей программе, имеющей то же значение, компилятор Python автоматически ставит строки, делая их оба сохраненными в том же месте памяти. (Обратите внимание, что это не всегда всегда , а правила для того, когда это происходит, довольно запутаны, поэтому, пожалуйста, не полагайтесь на это поведение в производственном коде!) [/ G12]
Поскольку в вашем интерактивном сеансе обе строки фактически хранятся в одном и том же месте памяти, у них одинаковое identity , поэтому оператор
is
работает так, как ожидалось. Но если вы построите строку другим способом (даже если эта строка содержит точно одинаковые символы), то строка может быть равна , но это не одна и та же строка , то есть она имеет другое тождество , поскольку оно хранится в другом месте в памяти.
Из моего ограниченного опыта работы с python is
используется для сравнения двух объектов, чтобы увидеть, являются ли они одним и тем же объектом, а не двумя разными объектами с одинаковым значением. ==
используется для определения идентичности значений.
Вот хороший пример:
>>> s1 = u'public'
>>> s2 = 'public'
>>> s1 is s2
False
>>> s1 == s2
True
s1
- строка в Юникоде, а s2
- обычная строка. Они не одного типа, но имеют одинаковое значение.
В последнее время вы можете использовать функцию intern, чтобы убедиться, что вы получаете ссылку на одну и ту же строку:
>>> a = intern('a')
>>> a2 = intern('a')
>>> a is a2
True
Как указано выше, вы, вероятно, не должны делать является определение равенства по строкам. Но это может быть полезно узнать, есть ли у вас какое-то странное требование использовать is
.
Обратите внимание, что функция-интернатура перешла из встроенной функции в модуль sys
для Python 3.
is
сравнивает местоположение памяти. Он используется для сравнения уровня объекта.
==
будет сравнивать переменные в программе. Он используется для проверки на уровне ценности.
is
проверяет эквивалентность уровня адреса
==
проверяет эквивалентность уровня значения
Если вы не уверены, что делаете, используйте '=='. Если у вас есть немного больше знаний об этом, вы можете использовать «is» для известных объектов, таких как «None».
В противном случае вы будете удивлены, почему все не работает и почему это происходит:
>>> a = 1
>>> b = 1
>>> b is a
True
>>> a = 6000
>>> b = 6000
>>> b is a
False
Я даже не уверен, что некоторые вещи гарантированно останутся неизменными между различными версиями / реализациями python.
Я думаю, что это связано с тем, что, когда сравнение «is» оценивается как false, используются два разных объекта. Если он оценивает значение true, это означает, что внутри он использует один и тот же точный объект, а не создает новый, возможно, потому, что вы создали их за долю в 2 или около того секунд и потому, что между ним нет большого промежутка времени и использует тот же объект.
Вот почему вы должны использовать оператор равенства ==
, а не is
, чтобы сравнить значение строкового объекта.
>>> s = 'one'
>>> s2 = 'two'
>>> s is s2
False
>>> s2 = s2.replace('two', 'one')
>>> s2
'one'
>>> s2 is s
False
>>>
В этом примере я сделал s2, который был другим строковым объектом, ранее равным «одному», но это не тот же объект, что и s
, потому что интерпретатор не использовал тот же объект, что и я, один ', если бы я сделал это, это сделало бы их одним и тем же объектом.
is
- тестирование идентичности, ==
- проверка равенства. Это означает, что is
- это способ проверить, являются ли две вещи одинаковыми вещами или просто эквивалентны.
Скажем, у вас есть простой объект person
. Если он называется «Джек» и ему «23 года», он эквивалентен другому 23-летнему Джеку, но его не одному человеку.
class Person(object):
def __init__(self, name, age):
self.name = name
self.age = age
def __eq__(self, other):
return self.name == other.name and self.age == other.age
jack1 = Person('Jack', 23)
jack2 = Person('Jack', 23)
jack1 == jack2 #True
jack1 is jack2 #False
Они того же возраста, не один и тот же экземпляр человека. Строка может быть эквивалентна другой, но это не тот же объект.
Я отвечаю на вопрос, даже если вопрос старен, потому что ни один из ответов выше не цитирует ссылку на язык
На самом деле оператор проверяет идентификаторы и == проверяет оператор на равенство,
Из справочника по языку:
Типы затрагивают почти все аспекты поведения объекта. Даже значение идентичности объектов в некотором смысле влияет: для неизменяемых типов операции, которые вычисляют новые значения, могут фактически возвращать ссылку на любой существующий объект с тем же типом и значением, в то время как для изменяемых объектов это недопустимо. Например, после a = 1; b = 1, a и b могут или не могут ссылаться на один и тот же объект со значением один, в зависимости от реализации, но после c = []; d = [], c и d гарантированно относятся к двум различным уникальным, вновь созданным пустым спискам. (Обратите внимание, что c = d = [] присваивает один и тот же объект как c, так и d.)
, поэтому из вышеприведенного утверждения мы можем заключить, что строки, которые являются неизменяемым, могут сбой при проверке с помощью «is» и может проверяться успешно, если отмечено с помощью «is»
То же самое относится к int, кортежу, которые также являются неизменяемыми типами
Ключевое слово is
- это тест для идентификации объекта, а ==
- сравнение значений.
Если вы используете is
, результат будет истинным тогда и только тогда, когда объект является тот же объект. Однако ==
будет истинным в любое время, когда значения объекта будут одинаковыми.
Эквивалентность тестового значения оператора ==
. Оператор is
проверяет идентичность объекта, Python проверяет, действительно ли эти два являются одним и тем же объектом (т. Е. Живут по одному и тому же адресу в памяти).
>>> a = 'banana'
>>> b = 'banana'
>>> a is b
True
В этом примере Python создал только одну строку объект, и оба a
и b
ссылаются на него. Причина в том, что Python внутренне кэширует и использует несколько строк в качестве оптимизации, на самом деле в памяти есть только строка «банан», разделяемая a и b; Чтобы вызвать нормальное поведение, вам нужно использовать более длинные строки:
>>> a = 'a longer banana'
>>> b = 'a longer banana'
>>> a == b, a is b
(True, False)
Когда вы создаете два списка, вы получаете два объекта:
>>> a = [1, 2, 3]
>>> b = [1, 2, 3]
>>> a is b
False
В этом случае мы сказали бы: что эти два списка эквивалентны, потому что они имеют одинаковые элементы, но не идентичны, потому что они не являются одним и тем же объектом. Если два объекта идентичны, они также эквивалентны, но если они эквивалентны, они не обязательно идентичны.
Если a
ссылается на объект и вы назначаете b = a
, то обе переменные ссылаются на тот же объект:
>>> a = [1, 2, 3]
>>> b = a
>>> b is a
True
Я считаю, что это известно как «интернированные» строки. Python делает это, так же как и Java, а также C и C ++ при компиляции в оптимизированных режимах.
Если вы используете две идентичные строки, вместо того, чтобы тратить память на создание двух строковых объектов, все интернированные строки с одинаковыми содержимое указывает на одну и ту же память.
Это приводит к тому, что оператор Python «is» возвращает True, потому что две строки с тем же содержимым указывают на один и тот же строковый объект. Это также произойдет в Java и в C.
Это полезно только для экономии памяти. Вы не можете полагаться на него, чтобы проверить равенство строк, потому что различные интерпретаторы, компиляторы и JIT-механизмы не всегда могут это сделать.