Ответ 1
Большое спасибо @eryksun за исправления!
Это связано с вызовом механизма interning
в Python:
Введите строку в таблицу "интернированных" строк и верните интернированная строка - это сама строка или копия. Внутренние струны полезно получить небольшую производительность при поиске в словаре - если ключи в словаре интернированы, а ключ поиска интернирован, ключевые сравнения (после хэширования) могут быть сделаны с помощью сравнения указателя вместо сравнения строк. Обычно имена, используемые в Python программы автоматически интернированы, а словари, используемые для хранения атрибуты модуля, класса или экземпляра имеют интернированные ключи.
Изменено в версии 2.3: Интернированные строки не являются бессмертными (например, они раньше был в Python 2.2 и раньше); вы должны держать ссылку на возвращаемое значение intern() вокруг, чтобы извлечь выгоду из него.
CPython автоматически ставит short определенные строки (1 буквенные строки, ключевые слова, строки без пробелов, которые были назначены), чтобы увеличить скорость поиска и скорость сравнения: например, 'dog' is 'dog'
будет указателем сравнение вместо полного сравнения строк. Тем не менее, для автоматического интернирования для всех (более длинных) строк требуется гораздо больше памяти, что не всегда возможно, и, следовательно, они могут не иметь одинакового идентификатора, что делает результаты id()
разными, например,:
# different id when not assigned
In [146]: id('dog')
Out[146]: 4380547672
In [147]: id('dog')
Out[147]: 4380547552
# if assigned, the strings will be interned (though depends on implementation)
In [148]: a = 'dog'
In [149]: b = 'dog'
In [150]: id(a)
Out[150]: 4380547352
In [151]: id(b)
Out[151]: 4380547352
In [152]: a is b
Out[152]: True
Для целых чисел, по крайней мере, на моей машине, CPython автоматически будет автоматизировать до 256 автоматически:
In [18]: id(256)
Out[18]: 140511109257408
In [19]: id(256)
Out[19]: 140511109257408
In [20]: id(257)
Out[20]: 140511112156576
In [21]: id(257)
Out[21]: 140511110188504
ОБНОВЛЕНИЕ благодаря @eryksun: в этом случае строка 'a string'
не интернирована, потому что CPython только ставит строки без пробелов, а не из-за длины, которую я сразу принял: например, буквы ASCII, цифры и подчеркивание.
Для получения дополнительной информации вы также можете обратиться к Alex Martelli здесь.