is vs == для строк: 'py'*2 и 'pypy'

is vs == для строк: 'py'*2 и 'pypy'

@python_quiz

Разберем этот квиз

Коротко: в выражении слияния и сравнения строк важно различать тождество объектов (is) и равенство значений (==). Ниже разберём код квиза, объясним поведение и покажем практические примеры.

Условие (код из квиза)

python

Что происходит и почему

  • Оператор == сравнивает значения объектов. Для строк это посимвольное сравнение — если последовательности символов одинаковы, результат True.
  • Оператор is проверяет, указывают ли две переменные на один и тот же объект в памяти (тождество), а не на равные по значению объекты.

В приведённом фрагменте значение строк одинаковое: 'py' * 2 даёт строку "pypy", которая по содержанию равна литералу 'pypy'. Поэтому == вернёт True.

Но объект, созданный выражением 'py' * 2, обычно создаётся в runtime как новый объект. Литеральный 'pypy' может быть создан другим объектом (или инторниться), поэтому is, как правило, вернёт False. Однако поведение зависит от реализации и оптимизаций интерпретатора (например, CPython может интернировать некоторые строки), поэтому is не гарантирует совпадение для эквивалентных строк.

Демонстрация в интерпретаторе

python

Типичный вывод:

id() показывает, что объекты находятся в разных ячейках памяти.

Исключения и нюансы

  • Компиляция и интернирование: смежные строковые литералы компилируются вместе:
python

В этом случае компилятор может создать один и тот же объект для c и d, и is даст True в некоторых версиях/сборках интерпретатора.

  • Оператор * выполняется во время выполнения, поэтому 'py'*2 обычно создаёт новый объект, и совпадение по идентичности не гарантировано.
  • CPython может интернировать некоторые короткие строки автоматически, но это поведение не документировано как универсальное и может менятьcя между версиями.

Как явно получить единый объект (если нужно)

Если по какой-то причине требуется, чтобы одинаковые строки были буквально одним и тем же объектом, можно использовать sys.intern:

python

sys.intern гарантированно помещает строку в таблицу интернированных строк и возвращает канонический объект для данного значения.

Рекомендации и вывод

  • Для сравнения строк используйте == — это корректно и понятно по смыслу.
  • is используйте для проверки тождественности объектов в тех случаях, когда важно именно то, что переменные ссылаются на один объект (например, проверка на None: x is None).
  • Не полагайтесь на is для сравнения строк — поведение может зависеть от реализации и оптимизаций интерпретатора.

Коротко: строковые значения, полученные разными способами, могут быть равны по содержимому, но не быть тем же объектом в памяти. Для значения используйте ==; is — для объектов/одиночных синглтонов.

Report Page