Интернирование строк Python
хотя этот вопрос не имеет никакого реального использования на практике, мне любопытно, как Python делает интернирование строк. Я заметил следующее.
>> "string" is "string"
>> True
это, как я ожидал.
вы также можете сделать это.
>> "strin"+"g" is "string"
>> True
и это очень умно!
но вы не можете этого сделать.
>> s1 = "strin"
>> s2 = "string"
>> s1+"g" is s2
>> False
почему бы Python не оценить s1+"g"
, поймите, что это то же самое, что s1
и указал им на тот же адрес? Что на самом деле происходит в этом последнем блоке, чтобы он вернулся False
?
2 ответа:
это зависит от реализации, но ваш интерпретатор, вероятно, интернирует константы времени компиляции, но не результаты выражений времени выполнения.
в дальнейшем я использую CPython 2.7.3.
во втором примере, выражение
"strin"+"g"
вычисляется во время компиляции и заменить"string"
. Это заставляет первые два примера вести себя одинаково.если мы рассмотрим байт-коды, мы увидим, что они точно такие же то же самое:
# s1 = "string" 2 0 LOAD_CONST 1 ('string') 3 STORE_FAST 0 (s1) # s2 = "strin" + "g" 3 6 LOAD_CONST 4 ('string') 9 STORE_FAST 1 (s2)
третий пример включает конкатенацию во время выполнения, результат которой не интернируется автоматически:
# s3a = "strin" # s3 = s3a + "g" 4 12 LOAD_CONST 2 ('strin') 15 STORE_FAST 2 (s3a) 5 18 LOAD_FAST 2 (s3a) 21 LOAD_CONST 3 ('g') 24 BINARY_ADD 25 STORE_FAST 3 (s3) 28 LOAD_CONST 0 (None) 31 RETURN_VALUE
если бы Вы были вручную
intern()
в результате третьего выражения вы получите тот же объект, что и раньше:>>> s3a = "strin" >>> s3 = s3a + "g" >>> s3 is "string" False >>> intern(s3) is "string" True
корпус 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