Вы действительно не должны видеть один и тот же идентификатор дважды в строке, но CPython имеет оптимизацию для конкатенации строк с +
, которая не совсем подчиняется всем правилам, которые должны.
Когда CPython видит операцию в форме x = x + something
или x += something
, если x
ссылается на строку и x
содержит ссылку только на эту строку, то CPython будет увеличивать строка с realloc
вместо создания нового строкового объекта. В зависимости от деталей доступной памяти, realloc
может изменять размер выделенной памяти на месте или выделять новую память. Если он изменяет размер выделения, id
объекта остается неизменным. Вы можете увидеть реализацию в unicode_concatenate
в Python/ceval.c
.
Эта оптимизация в основном в порядке, поскольку проверка refcount гарантирует, что она ведет себя в основном , как если бы строки были действительно неизменяемыми и была создана новая строка. Однако в x = x + stuff
старая строка и новая строка должны иметь кратковременное время жизни, потому что новая строка должна появиться до того, как присваивание завершит время жизни старой строки, поэтому должно невозможно, чтобы значения идентификаторов были равны.
id
- это один из немногих способов, которым оптимизация заметно отличается от того, если не произошло строковой мутации. Разработчики языка, похоже, решили, что с этим все в порядке.