В чем разница в поведении `[]` и `list () '? - PullRequest
3 голосов
/ 09 апреля 2019
print(id([]) == id([]))
# prints 'True'

print(id(list()) == id(list()))
# prints 'False'

x = []
y = []
print(id(x) == id(y))
# prints 'False'

Почему list() ведет себя иначе, чем [], в отношении вышеуказанного кода?

Ответы [ 2 ]

5 голосов
/ 09 апреля 2019

При третьем сравнении id вы сравниваете значения идентификаторов двух объектов с перекрывающимися временами жизни.Это должно вернуть False по контракту функции id.Вы бы видели то же поведение с list().

. В обоих ваших первых двух id сравнениях соответствующие объекты имеют непересекающиеся времена жизни.Являются ли значения идентификаторов объектов с непересекающимися временами жизни одинаковыми, это деталь реализации, и вы не должны полагаться на то, что они так или иначе.Поведение может быть изменено без уведомления.

В текущем CPython значения идентификаторов совпадают с [], потому что [] использует код операции BUILD_LIST, который вызываетфункция C PyList_New и PyList_New использует свободный список освобожденных структур заголовка списка для ускорения выделения:

PyObject *
PyList_New(Py_ssize_t size)
{
    ...
    if (numfree) {
        numfree--;
        op = free_list[numfree];
        _Py_NewReference((PyObject *)op);

Когда списки освобождаются, буфер, содержащий элементуказатели освобождаются, но (до максимального размера свободного списка) заголовок, содержащий информацию о таких вещах, как тип объекта, счет, емкость и т. д. попадает в свободный список :

static void
list_dealloc(PyListObject *op)
{
    ...
    if (numfree < PyList_MAXFREELIST && PyList_CheckExact(op))
        free_list[numfree++] = op;
    else
        Py_TYPE(op)->tp_free((PyObject *)op);
    Py_TRASHCAN_SAFE_END(op)
}

Список, созданный первым [], умирает перед вторым [] выражением, поэтому его заголовок попадает в свободный список, а затем снова используется вторым [].Значение id основано на адресе этого заголовка, поэтому оба списка имеют одинаковое значение идентификатора.

Напротив, list() проходит через tp_new, tp_init и list 's *.1036 * - это PyType_GenericNew, который не проходит через тот же список бесплатных.PyType_GenericNew происходит выделение двух списков в разной памяти, создавая разные значения идентификаторов.

4 голосов
/ 09 апреля 2019

id(object) возвращает идентификатор объекта.

Выражение == оценивается как True, если объекты, на которые ссылаются переменные, равны (имеют одинаковое содержимое).

Таким образом, когда вы используете конструктор list() каждый раз, когда создается новый объект, и его идентификатор отличается, следовательно, он оценивается как ложный, даже если новый объект немедленно отбрасывается, он создается сначала, таким образом, различные Я бы.

Напротив, [] является буквальным (более быстрый способ создания объекта) и всегда имеет один и тот же идентификатор, но, поскольку он создает новый объект, новый объект также получает свой новый идентификатор.

TLDR; [] является литералом и поэтому имеет фиксированный идентификатор, list() создает новый объект, x=[] y=[] создает новый объект x и y, отсюда и идентификатор x и y - это не одно и то же, list() каждый раз создает новый объект, поэтому разные идентификаторы при каждом вызове.

Также x = [] будет быстрее, чем x = list(), но это всего лишь нота, и я не могу понять, как сделать ее маленькой, и поставить ее как ноту:)

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...