How is the Python list initialization with square brackets implemented? Does it call some preexisting function, such as __setitem__
, one by one until the list is created or is there a separate function that takes in a variable number of arguments and creates a list?
l = [1, 2, 3, 4, 5]
For example, how is the above list created? I am interested in the process by which the list is constructed in the source code. Either the actual code itself, or the steps that are carried out to store the list into memory.
You can compile that particular code snippet and examine the byte code with dis
:
In [1]: import dis
In [2]: code = compile('l = [1, 2, 3, 4, 5]', '', 'exec')
In [3]: dis.dis(code)
1 0 LOAD_CONST 0 (1)
3 LOAD_CONST 1 (2)
6 LOAD_CONST 2 (3)
9 LOAD_CONST 3 (4)
12 LOAD_CONST 4 (5)
15 BUILD_LIST 5
18 STORE_NAME 0 (l)
21 LOAD_CONST 5 (None)
24 RETURN_VALUE
Particularly line 15, BUILD_LIST
, where the list is actually built. No constructor or function is actually called, as is in this case:
In [1108]: dis.dis(compile('l = list()', '', 'exec'))
1 0 LOAD_NAME 0 (list)
3 CALL_FUNCTION 0 (0 positional, 0 keyword pair)
6 STORE_NAME 1 (l)
9 LOAD_CONST 0 (None)
12 RETURN_VALUE
Where you see in line 3, CALL_FUNCTION
, the call is made to the list
class' constructor.
The grammar of the language parses the source code to build the parse tree such that, the list is created and ready to use at runtime.
For details on the implementation of list objects, have a look here.
Edit: Found the implementation detail for the bytecode. Here it is. BUILD_LIST
:
TARGET(BUILD_LIST)
x = PyList_New(oparg);
if (x != NULL) {
for (; --oparg >= 0;) {
w = POP();
PyList_SET_ITEM(x, oparg, w);
}
PUSH(x);
DISPATCH();
}
break;
Contrast with CALL_FUNCTION
:
TARGET(CALL_FUNCTION)
{
PyObject **sp;
PCALL(PCALL_ALL);
sp = stack_pointer;
#ifdef WITH_TSC
x = call_function(&sp, oparg, &intr0, &intr1);
#else
x = call_function(&sp, oparg);
#endif
stack_pointer = sp;
PUSH(x);
if (x != NULL)
DISPATCH();
break;
}
The latter makes an actual function call while the former allocates the object with PyList_New
.