Здесь есть два момента.
Во-первых, Python действительно создает новый символ с __getitem__
вызова, но только если этот символ имеет порядковое значение больше чем 256.
Например:
>>> s = chr(256)
>>> s[0] is s
True
>>> t = chr(257)
>>> t[0] is t
False
Это потому что внутренне, скомпилированная функция getitem
проверяет порядковое значение одиночного chracter и вызывает get_latin1_char
, если это значение равно 256 или меньше. Это позволяет использовать односимвольные строки. В противном случае создается новый объект unicode.
Вторая проблема касается сбора мусора и показывает, что интерпретатор может очень быстро использовать адреса памяти. Когда вы пишете:
>>> s = t # = chr(257)
>>> t[0] is s[0]
False
Python сначала создает две новые одиночные символьные строки, а затем сравнивает их адреса памяти. Они имеют разные адреса (у нас есть разные объекты в соответствии с приведенным выше объяснением), поэтому сравнение объектов с is
возвращает False.
С другой стороны, мы можем иметь, казалось бы, парадоксальная ситуация, что:
>>> id(t[0]) == id(s[0])
True
Но это потому, что переводчик быстро повторно адрес памяти t[0]
, когда он создает новую строку s[0]
на более поздний момент время.
Если вы исследуете байткод производит эту линию (например, с dis
- смотри ниже), вы видите, что адреса для каждой стороны распределяются одна за другой (новый строковый объект создается, а затем id
называется на нем) ,
Обращения к объекту t[0]
сбрасываются до нуля, как только возвращается id(t[0])
(мы проводим сравнение по целым числам, а не по самому объекту). Это означает, что s[0]
может повторно использовать тот же адрес памяти, когда он будет создан после этого.
Вот разобранном байткод для линии id(t[0]) == id(s[0])
который я аннотированный.
Вы можете видеть, что срок службы t[0]
заканчивается до создания s[0]
(на нем нет ссылок), поэтому его память может быть использована повторно.
2 0 LOAD_GLOBAL 0 (id)
3 LOAD_GLOBAL 1 (t)
6 LOAD_CONST 1 (0)
9 BINARY_SUBSCR # t[0] is created
10 CALL_FUNCTION 1 # id(t[0]) is computed...
# ...lifetime of string t[0] over
13 LOAD_GLOBAL 0 (id)
16 LOAD_GLOBAL 2 (s)
19 LOAD_CONST 1 (0)
22 BINARY_SUBSCR # s[0] is created...
# ...free to reuse t[0] memory
23 CALL_FUNCTION 1 # id(s[0]) is computed
26 COMPARE_OP 2 (==) # the two ids are compared
29 RETURN_VALUE
Ваш символ на самом деле является строка с одним элементом, так что да, доступ полукокса по индексу создает новую строку длины 1. –
я получаю this- 'ValueError: Chr() ARG не в диапазоне (256) 'при Я запускаю this-'s = chr (8263)' – CrakC
, как дубликат объясняет 't [0] равен s [0] -> False', даже если' id (t [0]) == id (s [0]) -> Правда'? –