Вы использовали id()
неправильно. id([])
принимает идентификатор памяти объекта немедленно отбрасывается. В конце концов, ничто не ссылается на него больше, как только id()
делается с ним. Итак, в следующий раз, когда вы используете id([])
Python видит возможность повторно использовать память, и вот, эти адреса действительно то же самое.
Однако это деталь реализации, на которую вы не можете положиться, и она не всегда сможет повторно использовать адрес памяти.
Обратите внимание, что id()
значения являются уникальными в течение времени жизни объекта, см documentation:
Это целое число, которое гарантированно будет уникальным и постоянным для этого объекта в течение всего срока службы. Два объекта с неперекрывающимися сроками службы могут иметь одинаковое значение id()
.
(Смелый акцент мой).
То, что id(list())
не может повторно использовать расположение памяти, возможно, связано с дополнительными мучениями кучи, вызванными нажатием текущего кадра в стеке, чтобы вызвать функцию, а затем снова щелкнуть ее, когда возвращается вызов list()
.
И []
, и list()
Производите новый пустой объект списка; но вы должны сначала создать ссылки на эти отдельные списки (здесь a
и b
):
>>> a, b = [], []
>>> a is b
False
>>> id(a) == id(b)
False
>>> a, b = list(), list()
>>> a is b
False
>>> id(a) == id(b)
False
То же самое происходит, когда вы использовали [].__repr__
. Интерактивный интерпретатор Python имеет особое глобальное имя, _
, что вы можете использовать для ссылки на последний результат, полученный:
>>> [].__repr__
<method-wrapper '__repr__' of list object at 0x10e011608>
>>> _
<method-wrapper '__repr__' of list object at 0x10e011608>
Это создает дополнительные ссылки, поэтому метод __repr__
, и расширением, пустой список вы создали для него по-прежнему считается активным. Местоположение памяти не освобождается и недоступно для следующего создаваемого вами списка.
Но выполнение [].__repr__
снова, Python теперь связывает _
с этим новым объектом метода. Внезапно предыдущий метод __repr__
больше не ссылается ни на что и может быть освобожден, а также объект списка.
В третий раз вы выполняете [].__repr__
первой ячейки памяти снова доступен для повторного использования, так Python делает только что:
>>> [].__repr__ # create a new method
<method-wrapper '__repr__' of list object at 0x10e00cb08>
>>> _ # now _ points to the new method
<method-wrapper '__repr__' of list object at 0x10e00cb08>
>>> [].__repr__ # so the old address can be reused
<method-wrapper '__repr__' of list object at 0x10e011608>
Вы никогда не создавать более двух списки; предыдущий (все еще ссылающийся на _
) и текущий. Если вы хотите увидеть больше мест памяти, используйте переменные, чтобы добавить другую ссылку.