Другой дубликат спрашивал, почему две равные строки обычно не идентичны, на что здесь нет ответа:
>>> x = 'a'
>>> x += 'bc'
>>> y = 'abc'
>>> x == y
True
>>> x is y
False
Итак, почему это не одна и та же строка? Особенно с учетом этого:
>>> z = 'abc'
>>> w = 'abc'
>>> z is w
True
Отложим на время вторую часть. Как первое могло быть правдой?
Интерпретатор должен иметь «таблицу интернирования», таблицу, отображающую строковые значения для строковых объектов, поэтому каждый раз, когда вы пытаетесь создать новую строку с содержимым 'abc'
, вы получаете тот же объект. В Википедии есть более подробное обсуждение того, как работает интернирование.
А в Python есть таблица интернирования строк; вы можете вручную интернировать строки с помощью sys.intern
метода.
На самом деле, Python будет разрешено автоматически стажер любого неизменных типов, но не требуется , чтобы сделать это. Различные реализации будут использовать разные значения.
CPython (реализация, которую вы используете, если вы не знаете, какую реализацию вы используете) автоматически обрабатывает небольшие целые числа и некоторые специальные синглтоны, такие как False
, но не строки (или большие целые числа, или маленькие кортежи, или что-то еще). Вы можете легко это увидеть:
>>> a = 0
>>> a += 1
>>> b = 1
>>> a is b
True
>>> a = False
>>> a = not a
>>> b = True
a is b
True
>>> a = 1000
>>> a += 1
>>> b = 1001
>>> a is b
False
Хорошо, но почему были z
и w
идентичны?
Это не интерпретатор автоматически интернирует, это значения сворачивания компилятора.
Если же во время компиляции строка появляется дважды в одном модуле (что именно это означает, трудно определить, что это не то же самое , как строковый литерал, потому что r'abc'
, 'abc'
и 'a' 'b' 'c'
все разные литералы , но та же строка, но легко понять , интуитивно) компилятор создаст только один экземпляр строки с двумя ссылками.
Фактически, компилятор может пойти еще дальше: он 'ab' + 'c'
может быть преобразован 'abc'
оптимизатором, и в этом случае он может быть свернут вместе с 'abc'
константой в том же модуле.
Опять же, Python это разрешено, но не обязательно. Но в этом случае CPython всегда сворачивает небольшие строки (а также, например, небольшие кортежи). (Хотя компилятор команд интерактивного интерпретатора не выполняет ту же оптимизацию, что и компилятор «модуль за раз», поэтому вы не увидите точно таких же результатов в интерактивном режиме.)
Итак, что вы должны делать с этим как программист?
Ну… ничего. У вас почти никогда не будет причин беспокоиться об идентичности двух неизменяемых значений. Если вы хотите знать, когда можно использовать a is b
вместо a == b
, вы задаете неправильный вопрос. Просто используйте всегда, a == b
кроме двух случаев:
- Для более удобочитаемых сравнений с одноэлементными значениями, такими как
x is None
.
- Для изменяемых значений, когда вам нужно знать,
x
повлияет ли изменение на y
.