이 질문 에서 언급했듯이 목록 이해력은 list.append
후드에서 사용하므로 목록 크기 조정 메소드를 호출하여 전체적으로 할당합니다.
이것을 직접 보여주기 위해 실제로 dis
dissasembler를 사용할 수 있습니다 :
>>> code = compile('[x for x in iterable]', '', 'eval')
>>> import dis
>>> dis.dis(code)
1 0 LOAD_CONST 0 (<code object <listcomp> at 0x10560b810, file "", line 1>)
2 LOAD_CONST 1 ('<listcomp>')
4 MAKE_FUNCTION 0
6 LOAD_NAME 0 (iterable)
8 GET_ITER
10 CALL_FUNCTION 1
12 RETURN_VALUE
Disassembly of <code object <listcomp> at 0x10560b810, file "", line 1>:
1 0 BUILD_LIST 0
2 LOAD_FAST 0 (.0)
>> 4 FOR_ITER 8 (to 14)
6 STORE_FAST 1 (x)
8 LOAD_FAST 1 (x)
10 LIST_APPEND 2
12 JUMP_ABSOLUTE 4
>> 14 RETURN_VALUE
>>>
코드 객체 LIST_APPEND
의 디스 어셈블리 에서 opcode를 확인하십시오 <listcomp>
. 로부터 문서 :
LIST_APPEND (i)
전화 list.append(TOS[-i], TOS)
. 목록 이해를 구현하는 데 사용됩니다.
이제리스트 반복 작업의 경우 다음을 고려할 때 진행중인 작업에 대한 힌트가 있습니다.
>>> import sys
>>> sys.getsizeof([])
64
>>> 8*10
80
>>> 64 + 80
144
>>> sys.getsizeof([None]*10)
144
따라서 크기 를 정확하게 할당 할 수있는 것 같습니다 . 소스 코드를 살펴보면 이것이 정확히 어떻게되는지 볼 수 있습니다.
static PyObject *
list_repeat(PyListObject *a, Py_ssize_t n)
{
Py_ssize_t i, j;
Py_ssize_t size;
PyListObject *np;
PyObject **p, **items;
PyObject *elem;
if (n < 0)
n = 0;
if (n > 0 && Py_SIZE(a) > PY_SSIZE_T_MAX / n)
return PyErr_NoMemory();
size = Py_SIZE(a) * n;
if (size == 0)
return PyList_New(0);
np = (PyListObject *) PyList_New(size);
즉, 여기에 : size = Py_SIZE(a) * n;
. 나머지 함수는 단순히 배열을 채 웁니다.
144 == sys.getsizeof([]) + 8*10)
8 포인터의 크기입니다.