Когда Python создает новые объекты списка для пустых списков?

Для меня имеет смысл следующее:

>>> [] is []
False

Учитывая, что списки изменяемы, я ожидаю, что [] будет новым пустым объектом списка каждый раз, когда он появляется в выражении. Однако, используя это объяснение, меня удивляет следующее:

id([]) == id([])
True

Почему? Каково объяснение?


person Loax    schedule 22.02.2014    source источник
comment
Я бы поставил ненулевую сумму денег на то, что id([]) == id([]) не является True на всех разновидностях питона. (да, проверено.) cPython имеет тенденцию перераспределять память таким образом, это деталь реализации.   -  person roippi    schedule 22.02.2014
comment
@roippi Я думаю, что на самом деле это случайность быстрого malloc/free/malloc. a = []; b = []; id(a) == id(b) # This is False   -  person Silas Ray    schedule 22.02.2014
comment
@roippi - я бы поспорил, что есть некоторые разновидности Python, в которых он иногда работает, а другие нет, в зависимости от того, когда именно запускается сборщик мусора.   -  person Malvolio    schedule 22.02.2014


Ответы (1)


В первом примере [] не совсем [], потому что списки изменяемы. Если бы это было не так, они могли бы безопасно сопоставляться с одним и тем же без проблем.

Во втором примере id([]) создает список, получает идентификатор и освобождает список. Во второй раз он создает список снова, но "помещает его на то же место", потому что больше ничего не произошло. id действует только во время жизни объекта, и в этом случае его время жизни практически равно нулю.

Из документов по идентификатору:

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


Разборка с комментариями:

   0 LOAD_GLOBAL              0 (id)    # load the id function
   3 BUILD_LIST               0         # create the first list
   6 CALL_FUNCTION            1         # get the id
   9 LOAD_GLOBAL              0 (id)    # load the id function
  12 BUILD_LIST               0         # create the second list
  15 CALL_FUNCTION            1         # get the id
  18 COMPARE_OP               2 (==)    # compare the two ids
  21 RETURN_VALUE                       # return the comparison

Обратите внимание, что нет STORE_FAST для сохранения списка. Поэтому он был отброшен сразу после передачи в функцию id.

person mhlester    schedule 22.02.2014
comment
Я помню, вы ответили на тот же вопрос незадолго до этого ;P - person zhangxaochen; 22.02.2014
comment
не этот, может это не ты, но должен быть дубликат - person zhangxaochen; 22.02.2014
comment
Хорошо ответил. Например, в def f(x, y): return id(x) == id(y), где и x, и y должны остаться в живых, f([], []) оценивается как False. - person Loax; 22.02.2014
comment
Именно так. Пока их время жизни перекрывается, они по определению должны иметь уникальные ключи. - person mhlester; 22.02.2014
comment
@mhlester Можете ли вы объяснить, почему два пустых кортежа объявлены независимо друг от друга, например a = (), b = () имеют тот же идентификатор? разборка показывает, что STORE_FAST вызывается дважды. Просто потому, что кортежи неизменны? - person Aamir Adnan; 13.06.2014
comment
@Aamir, да: поскольку они неизменяемы, они всегда будут хранить одно и то же значение. Если значение всегда одно и то же, зачем хранить его дважды? - person mhlester; 13.06.2014
comment
@mhlester Большое спасибо! - person Aamir Adnan; 13.06.2014