Хотя этот вопрос не имеет практического применения, мне любопытно, как Python выполняет интернирование строк. Я заметил следующее.
>>> "string" is "string"
True
Это как я и ожидал.
Вы тоже можете это сделать.
>>> "strin"+"g" is "string"
True
И это очень умно!
Но ты не можешь этого сделать.
>>> s1 = "strin"
>>> s2 = "string"
>>> s1+"g" is s2
False
Почему бы Python не оценить s1+"g"
и не понять, что это то же самое, s2
и не указать на тот же адрес? Что на самом деле происходит в этом последнем блоке, чтобы он вернулся False
?
"string1" + "s2"
,10 + 3*20
и т. Д.) Во время компиляции, но ограничивает результирующие последовательности всего 20 элементами (чтобы предотвратить[None] * 10**1000
чрезмерное расширение вашего байт-кода). Именно эта оптимизация обрушилась"strin" + "g"
на"string"
; результат короче 20 символов.intern()
функцией.intern
функцию в Python 3 - она перенесена на sys.internСлучай 1
>>> x = "123" >>> y = "123" >>> x == y True >>> x is y True >>> id(x) 50986112 >>> id(y) 50986112
Случай 2
>>> x = "12" >>> y = "123" >>> x = x + "3" >>> x is y False >>> x == y True
Теперь, ваш вопрос, почему же идентификатор в случае 1 , а не в случае 2.
В случае 1, вы назначили строковый литерал
"123"
кx
иy
.Поскольку строки неизменяемы, интерпретатору имеет смысл сохранить строковый литерал только один раз и указать все переменные на один и тот же объект.
Следовательно, вы видите идентификатор как идентичный.
В случае 2 вы изменяете
x
с помощью конкатенации. Обаx
иy
имеют одинаковые ценности, но не идентичны.Оба указывают на разные объекты в памяти. Следовательно, они разные,
id
иis
оператор вернулсяFalse
источник
id(x) != id(x)
например, потому что строка была перемещена в процессе оценки.x = "12" + "3"
вx = "123"
(конкатенацию двух строковых литералов в одном выражении), так что присвоение фактически выполняет поиск и находит ту же «внутреннюю» строку, что и дляy = "123"
.