Python-строку интернирование
хотя этот вопрос не имеет реальной пользы на практике, мне любопытно, как Python делает string interning. Я заметил следующее.
>> "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" to x и y. 
поскольку string неизменяемы, интерпретатору имеет смысл хранить строковый литерал только один раз и указывать все переменные на один и тот же объект.
Следовательно, вы видите id как идентичный.
в случае 2, вы изменяете x используя конкатенацию. Оба!--3--> и y имеет те же значения, но не тот же идентификатор.
Оба указывают на разные объекты в памяти. Следовательно, у них разные id и is оператор вернулся False
