is vs == для строк в Python
@python_quizРазберем этот квиз
Короткое условие — есть два выражения, одно строит строку операцией повторения, другое — литерал. Нужно понять, что выведет следующий код:

Результат выполнения — строка с двумя булевыми значениями:

Далее объясню, почему так происходит, разберу похожие случаи и дам практические рекомендации.
Что сравнивают is и ==
- Оператор
==сравнивает значения (содержимое объектов). Для строк — сравнение по символам. - Оператор
isпроверяет тождество объектов, то есть указывает, ссылаются ли переменные на один и тот же объект в памяти.
Для проверки равенства строк используйте ==. is применим для проверки идентичности (например, if x is None:).
Почему в примере получается (False, True)
a = 'py' * 2создаёт новую строку в момент выполнения (операция умножения/конкатенации выполняется во время выполнения кода), поэтомуaуказывает на отдельный объект.b = 'pypy'— это литерал. В CPython компилятор может оптимизировать литералы (интернинг, объединение соседних литералов и т.п.), поэтому переменная с литералом может ссылаться на другой объект.- Содержимое строк одинаково, поэтому
a == bдаёт True. - Объекты разные, поэтому
a is bдаёт False (в стандартной реализации поведение интернинга для такой операции не гарантировано).
Показательные примеры
1) Литералы могут быть одним объектом:

2) Сборка строки во время выполнения — другой объект:

3) Соседние строковые литералы объединяются на этапе компиляции:

4) Принудительный intern через sys.intern:

Важные замечания и рекомендации
- Поведение интернинга — деталь реализации (чаще встречается в CPython) и не входит в спецификацию языка. На разных реализациях Python (или даже в разных версиях CPython) поведение может отличаться.
- Никогда не полагайтесь на
isдля сравнения содержимого строк — используйте==. isуместен для проверки наNone(рекомендуетсяif x is None:) или для проверки тождественности объектов в тех ситуациях, где это нужно по семантике.- Если нужно гарантированно получить один и тот же объект для одинаковых строк (например, для экономии памяти или быстрых сравнений по ссылке), можно использовать
sys.intern, но делайте это осознанно.
Вывод
Операция умножения/конкатенации строк обычно создаёт новый объект во время выполнения, поэтому идентичность (оператор is) не гарантируется, хотя содержимое может быть одинаковым (оператор ==). Для проверки равенства содержимого всегда используйте ==; is — только для проверки тождественности/специальных случаев (например, None).