I would like to know why does python makes a LOAD_CONST
with the same value (the class name) twice when a class is defined. When I run this code:
from dis import dis
dis("class A(): pass")
This is the output I get:
1 0 LOAD_BUILD_CLASS
2 LOAD_CONST 0 (<code object A at 0x0000021DCE681B70, file "<dis>", line 1>)
4 LOAD_CONST 1 ('A')
6 MAKE_FUNCTION 0
8 LOAD_CONST 1 ('A')
10 CALL_FUNCTION 2
12 STORE_NAME 0 (A)
14 LOAD_CONST 2 (None)
16 RETURN_VALUE
Disassembly of <code object A at 0x0000021DCE681B70, file "<dis>", line 1>:
1 0 LOAD_NAME 0 (__name__)
2 STORE_NAME 1 (__module__)
4 LOAD_CONST 0 ('A')
6 STORE_NAME 2 (__qualname__)
8 LOAD_CONST 1 (None)
10 RETURN_VALUE
As you can see in the line 3 and 5 there are two LOAD_CONST
with the class name.
Why make a second LOAD_CONST
with the same data if the class name was already loaded? Does this has something to do with the MAKE_FUNCTION
between those LOAD_CONST
?
I'm running this on python 3.7.4 64-bit
TL;DR: type creation in CPython temporarily uses a function object for the class body. The first "A" is used for this function's name. The second "A" is used for the class name.
The rest of the post explains this disassembly in detail:
0 LOAD_BUILD_CLASS
Pushes builtins.__build_class__
onto the stack. It is later called by CALL_FUNCTION to construct a class.
2 LOAD_CONST 0 (<code object A at 0xCAFEF00D, file "<dis>", line 1>)
Pushes a code obj onto the stack (this actually contains the parsed class block - read on)
4 LOAD_CONST 1 ('A')
Pushes 'A' onto the stack
6 MAKE_FUNCTION 0
Pushes a new function object on the stack. This action also consumes the prev two things on the stack (the code obj for this function and its qualified name)
8 LOAD_CONST 1 ('A')
Pushes 'A' onto the stack again so that can be used as the second argument in builtins.__build_class__
, i.e. the class name.
10 CALL_FUNCTION 2
Consumes 'A' and a function object from the stack, calling __build_class__(<func>, 'A')
. The 2 after the op name is referring to the number of positional arguments munched. Right-most positional argument is on top of stack, so they will be: the class name 'A'
, and then the obj remaining from MAKE_FUNCTION which embodies the class definition. "Underneath" those arguments is the callable __build_class__
, which this op also consumes. None of the optional arguments accepted by __build_class__(func, name, /, *bases, [metaclass], **kwds) -> class
were provided.
12 STORE_NAME 0 (A)
A = <top of stack>
, essentially binding the newly created class obj in namespace
14 LOAD_CONST 2 (None)
RETURN_VALUE will return the top of stack, but a class statements exec doesn't need a return value, so load None
before returning.
16 RETURN_VALUE
We're done.
To understand why __build_class__
takes a function as the first argument, refer to this post from Guido. A function object is used for the class body, for convenience of implementation I guess.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With