2016-11-26 2 views
38

Может ли кто-нибудь объяснить следующее?Есть ли разница между [] и list() при использовании id()?

Почему id одинаковый, но списки разные?

>>> [] is [] 
False 
>>> id([]) == id([]) 
True 

Есть ли разница в создании списка?

>>> id(list()) == id(list()) 
False 
>>> id([]) == id([]) 
True 

Почему это происходит? Я получаю два разных списка. Почему не только один, три или более?

>>> [].__repr__ 
<method-wrapper '__repr__' of list object at 0x7fd2be868128> 
>>> [].__repr__ 
<method-wrapper '__repr__' of list object at 0x7fd2be868170> 
>>> [].__repr__ 
<method-wrapper '__repr__' of list object at 0x7fd2be868128> 
>>> [].__repr__ 
<method-wrapper '__repr__' of list object at 0x7fd2be868170> 

ответ

76

Вы использовали 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> 

Вы никогда не создавать более двух списки; предыдущий (все еще ссылающийся на _) и текущий. Если вы хотите увидеть больше мест памяти, используйте переменные, чтобы добавить другую ссылку.

 Смежные вопросы

  • Нет связанных вопросов^_^