Why does comparing strings using either '==' or 'is' sometimes produce a different result?
Почему сравнение строк с использованием '==' или 'is' иногда дает другой результат?
Двум строковым переменным присваивается одно и то же значение. s1 == s2 всегда возвращает True, но s1 is s2 иногда возвращает False.
Если я открою свой интерпретатор Python и проделаю то же самое is сравнение, оно завершится успешно:
>>> s1 = 'text' >>> s2 = 'text' >>> s1 is s2 True
Почему это?
Переведено автоматически
Ответ 1
is это проверка идентичности и == это проверка на равенство. То, что происходит в вашем коде, будет эмулироваться в интерпретаторе следующим образом:
>>> a = 'pub' >>> b = ''.join(['p', 'u', 'b']) >>> a == b True >>> a is b False
Итак, неудивительно, что они не совпадают, не так ли?
Другими словами: a is b эквивалентно id(a) == id(b)
Ответ 2
Другие ответы здесь правильные: is используется для сравнения идентичности, в то время как == используется для сравнения равенства. Поскольку вас интересует равенство (две строки должны содержать одинаковые символы), в этом случае is оператор просто неправильный, и вы должны использовать == вместо этого.
Причина, по которой is работает интерактивно, заключается в том, что (большинство) строковых литералов по умолчанию интернированы. Из Википедии:
Интернированные строки ускоряют сравнение строк, которое иногда является узким местом производительности в приложениях (таких как компиляторы и среды выполнения динамических языков программирования), которые в значительной степени зависят от хэш-таблиц со строковыми ключами. Без интернирования проверка того, что две разные строки равны, включает в себя проверку каждого символа обеих строк. Это происходит медленно по нескольким причинам: длина строк по своей сути равна O (n); обычно требуется чтение из нескольких областей памяти, что требует времени; и чтение заполняет кэш процессора, что означает, что для других нужд доступно меньше кэша. Для интернированных строк достаточно простого теста идентификации объекта после исходной операции интернирования; обычно это реализуется как тест на равенство указателей, обычно просто одна машинная команда без ссылки на память вообще.
Итак, когда у вас есть два строковых литерала (слова, которые буквально введены в исходный код вашей программы и заключены в кавычки) в вашей программе, которые имеют одинаковое значение, компилятор Python автоматически вставит строки, благодаря чему они обе будут храниться в одной ячейке памяти. (Обратите внимание, что это происходит не всегда, и правила, когда это происходит, довольно запутанны, поэтому, пожалуйста, не полагайтесь на такое поведение в производственном коде!)
Поскольку в вашем интерактивном сеансе обе строки фактически хранятся в одной и той же ячейке памяти, они имеют одинаковый идентификатор, поэтому is оператор работает так, как ожидалось. Но если вы создаете строку каким-либо другим методом (даже если эта строка содержит точно одинаковые символы), то строка может быть равной, но это не та же самая строка - то есть у нее другой идентификатор, потому что она хранится в другом месте памяти.
Ответ 3
is Ключевое слово является проверкой идентичности объекта, а == - сравнением значений.
Если вы используете is, результат будет истинным тогда и только тогда, когда объект является одним и тем же объектом. Однако, == будет истинным всякий раз, когда значения объекта совпадают.
Ответ 4
Напоследок следует отметить, что вы можете использовать функцию sys.intern, чтобы убедиться, что вы получаете ссылку на ту же строку:
>>> from sys import intern >>> a = intern('a') >>> a2 = intern('a') >>> a is a2 True
Как указывалось в предыдущих ответах, вам не следует использовать is для определения равенства строк. Но это может быть полезно знать, если у вас есть какие-то странные требования к использованию is.
Обратите внимание, что intern функция раньше была встроенной в Python 2, но она была перенесена в sys модуль в Python 3.