Как память Python управляет строковым объектом? - PullRequest
3 голосов
/ 19 октября 2019
for count in range(5):
    str1 = 'a' * count
    str2 = 'a' * count
    print(id(str1) == id(str2))

Output:
    True
    True
    False
    False
    False      

Почему мы получаем Ложь, потому что

str1 = 'aaa'
str2 = 'aaa'
print(id(str1) == id(str2)) # True 

Кто-нибудь объяснит это поведение памяти Python.

1 Ответ

5 голосов
/ 19 октября 2019

Давайте сначала выясним, что делает id():

Возвращает «идентичность» объекта. Это целое число, которое гарантированно будет уникальным и постоянным для этого объекта в течение его жизни. Два объекта с неперекрывающимися временами жизни могут иметь одинаковое значение id ().

Сведения о реализации CPython: Это адрес объекта в памяти.

ОК, поэтому вВообще, когда два имени указывают на один и тот же объект, они будут иметь один и тот же id().

Почему тогда у нас это есть?

str1 = 'aaa'
str2 = 'aaa'
print(id(str1) == id(str2)) # True

Это потому, что в CPython (эталонная реализация Python на C), строки кэшируются в хеш-таблице (по соображениям производительности), и дешевле иметь str1 и str2 для указания на одну и ту же память. Обратите внимание, что это можно сделать без особых неожиданных действий, поскольку строки в Python неизменны. Однако этот механизм запускается только для строк, которые полностью отображаются в интерпретаторе , например:

for i in range(5):
    a = eval('"' + 'a' * i + '"')
    b = eval('"' + 'a' * i + '"')
    print(id(a) == id(b), a, b)
True  
True a a
True aa aa
True aaa aaa
True aaaa aaaa

Любой механизм, создающий str динамически в интерпретаторе (т. е. кроме eval()), вне этого кэширования, как ваш пример, или:

a = 'aaa'
b = a[1:]
c = 'aa'
print(id(b) == id(c))
# False
print(id(b) == id(a[1:]))
# False

Для дальнейшего ознакомления внутреннее представление строк в Python описано более подробнодеталь в PEP 393 .

...