Почему сравнение строк с использованием '==' или 'is' иногда дает другой результат?

У меня есть программа Python, где две переменные установлены на значение 'public'. В условном выражении у меня есть сравнение var1 is var2, которое терпит неудачу, но если я изменю его на var1 == var2, он вернет True.

Теперь, если я открою свой интерпретатор Python и сделаю то же сравнение "есть", он преуспеет.

>>> s1 = 'public'
>>> s2 = 'public'
>>> s2 is s1
True

Что мне здесь не хватает?

Ответ 1

is - тестирование идентичности, == - проверка равенства. то, что происходит в вашем коде, будет эмулироваться в интерпретаторе следующим образом:

>>> a = 'pub'
>>> b = ''.join(['p', 'u', 'b'])
>>> a == b
True
>>> a is b
False

так что неудивительно, что они не то же самое, верно?

Другими словами: is - это id(a) == id(b)

Ответ 2

Другие ответы здесь верны: is используется для сравнения идентичности, а == используется для сравнения равенств. Так как вы заботитесь о равенстве (две строки должны содержать одни и те же символы), в этом случае оператор is просто ошибочен, и вместо этого вы должны использовать ==.

Причина is работает интерактивно в том, что (большинство) строковых литералов интернировано по умолчанию. Материал из Википедии:

Интернированные строки ускоряют строку сравнения, которые иногда являются узкое место в приложениях (например, компиляторы и динамические время программирования языка программирования), что в значительной степени полагаются на хеш-таблицы с строковые ключи. Без интернирования, проверяя, что две разные строки равны, включает в себя изучение каждого характер обеих строк. Это медленно по нескольким причинам: это по существу, O (n) в длине строки; обычно требуется чтение из нескольких областей памяти, которые занимать время; и чтение заполняет процессорный кеш, то есть меньше кэш доступен для других нужд. С интернированные строки, простой объект теста идентичности достаточно после оригинальная стажерская работа; это обычно реализуемый как указатель тест равенства, обычно один машинная инструкция без памяти ссылка вообще.

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

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

Ответ 3

Ключевое слово is - это тест для идентификации объекта, а == - сравнение значений.

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

Ответ 4

Наконец, вы можете использовать функцию intern, чтобы убедиться, что вы получаете ссылку на одну и ту же строку:

>>> a = intern('a')
>>> a2 = intern('a')
>>> a is a2
True

Как указывалось выше, вы, вероятно, не должны делать это, чтобы определить равенство по строкам. Но это может быть полезно узнать, есть ли у вас какое-то странное требование использовать is.

Обратите внимание, что функция intern перешла из встроенной функции в модуль sys для Python 3.

Ответ 5

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

Они одинакового возраста, но они не похожи на человека. Строка может быть эквивалентна другой, но это не тот же объект.

Ответ 7

Если вы не знаете, что делаете, используйте '=='. Если у вас есть немного больше знаний об этом, вы можете использовать "is" для известных объектов, таких как "Нет".

В противном случае вы будете удивлены, почему все не работает и почему это происходит:

>>> a = 1
>>> b = 1
>>> b is a
True
>>> a = 6000
>>> b = 6000
>>> b is a
False

Я даже не уверен, что некоторые вещи гарантированно останутся неизменными между различными версиями/реализациями python.

Ответ 8

Из моего ограниченного опыта работы с python is используется для сравнения двух объектов, чтобы увидеть, являются ли они тем же объектом, что и два разных объекта с одинаковым значением. == используется для определения идентичности значений.

Вот хороший пример:

>>> s1 = u'public'
>>> s2 = 'public'
>>> s1 is s2
False
>>> s1 == s2
True

s1 является строкой unicode, а s2 является обычной строкой. Они не одного типа, но имеют одинаковое значение.

Ответ 9

Я думаю, что это связано с тем фактом, что, когда сравнение '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, потому что интерпретатор не использовал тот же объект, который я изначально не назначал это "один", если бы у меня было это, это сделало бы их одним и тем же объектом.

Ответ 10

Я считаю, что это известно как "интернированные" строки. Python делает это, так же как и Java, а также C и С++ при компиляции в оптимизированных режимах.

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

В результате оператор Python "is" возвращает True, потому что две строки с одним и тем же содержимым указывают на один и тот же строковый объект. Это также произойдет в Java и в C.

Это полезно только для экономии памяти. Вы не можете полагаться на него, чтобы проверить соответствие строк, поскольку различные интерпретаторы, компиляторы и JIT-механизмы не всегда могут это сделать.

Ответ 11

Я отвечаю на вопрос, даже если вопрос старен, потому что никакие ответы выше не цитируют ссылку на язык

Фактически оператор-оператор проверяет идентификаторы и == для проверки равенства,

Из справочника по языку:

Типы затрагивают почти все аспекты поведения объекта. Даже значение значимости объекта в некотором смысле влияет: для неизменяемых типов операции , которые вычисляют новые значения, могут фактически возвращать ссылку на любой существующий объект с тем же типом и значением, тогда как для изменяемых объектов это недопустимо. Например, после a = 1; b = 1, a и b могут или не могут ссылаться на один и тот же объект со значением один, в зависимости от реализации, но после c = []; d = [], c и d гарантированно относятся к двум различным уникальным, вновь созданным пустым спискам. (Обратите внимание, что c = d = [] присваивает один и тот же объект как c, так и d.)

поэтому из вышеприведенного утверждения мы можем сделать вывод о том, что строки, которые являются неизменяемым, могут быть сбой при проверке с помощью "is" и могут проверяться успешно, когда отмечен с помощью "is"

То же самое относится к int, кортежу, которые также являются неизменяемыми типами

Ответ 12

Эквивалентность значения оператора ==. Оператор 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

Ответ 13

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

== будет сравнивать переменные в программе. Используется для проверки на уровне значения.

is проверяет эквивалентность на уровне адресов

== проверяет эквивалентность на уровне значений

Ответ 14

is - тестирование идентичности, == - проверка равенства (см. Документация на Python).

В большинстве случаев, если a is b, то a == b. Но есть исключения, например:

>>> nan = float('nan')
>>> nan is nan
True
>>> nan == nan
False

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

Ответ 15

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

s1='public'
s2='public'
sorted(s1) == sorted(s2)

Выше код даст результат как TRUE

s1='public'
s2='publci'
sorted(s1) == sorted(s2)

Выше код даст результат как TRUE

s1='public'
s2='publca'
sorted(s1) == sorted(s2)

Выше код даст результат как FALSE