Say I do:
#!/usr/bin/env python
# encoding: utf-8
class A(object):
pass
Now I disassemble it:
python -m dis test0.py
4 0 LOAD_CONST 0 ('A')
3 LOAD_NAME 0 (object)
6 BUILD_TUPLE 1
9 LOAD_CONST 1 (<code object A at 0x1004ebb30, file "test0.py", line 4>)
12 MAKE_FUNCTION 0
15 CALL_FUNCTION 0
18 BUILD_CLASS
19 STORE_NAME 1 (A)
22 LOAD_CONST 2 (None)
25 RETURN_VALUE
Now I add some statements in the class definition:
#!/usr/bin/env python
# encoding: utf-8
class A(object):
print 'hello'
1+1
pass
And I disassemble again:
4 0 LOAD_CONST 0 ('A')
3 LOAD_NAME 0 (object)
6 BUILD_TUPLE 1
9 LOAD_CONST 1 (<code object A at 0x1004ebb30, file "test0.py", line 4>)
12 MAKE_FUNCTION 0
15 CALL_FUNCTION 0
18 BUILD_CLASS
19 STORE_NAME 1 (A)
22 LOAD_CONST 2 (None)
25 RETURN_VALUE
What don't the new statements appear in the new bytecode?
What is.class File and Bytecode When Java source file is compiled by Java compiler it is converted into Java class file with.class extension. The Java class file contains Java bytecode (highly optimized set of instructions) which is executed by Java Virtual Machine (JVM).
Bytecode is computer object code that an interpreter converts into binary machine code so it can be read by a computer's hardware processor. The interpreter is typically implemented as a virtual machine (VM) that translates the bytecode for the target platform. The machine code consists of a set of instructions that the processor understands.
A Java programmer does not need to be aware of or understand Java bytecode at all. However, as suggested in the IBM developerWorks journal, "Understanding bytecode and what bytecode is likely to be generated by a Java compiler helps the Java programmer in the same way that knowledge of assembly helps the C or C++ programmer.".
If executing bytecode in a virtual machine is undesirable, a developer can also compile Java source code or bytecode directly to native machine code with tools such as the GNU Compiler for Java (GCJ). Some processors can execute Java bytecode natively. Such processors are termed Java processors .
The new statements are stored in nested bytecode. You can see in your disassembly that another code object is loaded:
9 LOAD_CONST 1 (<code object A at 0x1004ebb30, file "test0.py", line 4>)
You need to inspect that code object instead. That's because the class body is executed just like a function object, and the local namespace that call produces is then used to form the class members.
Demo:
>>> import dis
>>> def wrapper():
... class A(object):
... pass
...
>>> dis.dis(wrapper)
2 0 LOAD_CONST 1 ('A')
3 LOAD_GLOBAL 0 (object)
6 BUILD_TUPLE 1
9 LOAD_CONST 2 (<code object A at 0x104b99930, file "<stdin>", line 2>)
12 MAKE_FUNCTION 0
15 CALL_FUNCTION 0
18 BUILD_CLASS
19 STORE_FAST 0 (A)
22 LOAD_CONST 0 (None)
25 RETURN_VALUE
>>> dis.dis(wrapper.__code__.co_consts[2])
2 0 LOAD_NAME 0 (__name__)
3 STORE_NAME 1 (__module__)
3 6 LOAD_LOCALS
7 RETURN_VALUE
This is the same setup as your first sample; the class body is accessed via the wrapper.__code__.co_consts
tuple, which is what the LOAD_CONST
byte code refers to; the index is given as 2
.
Now we can add a class body:
>>> def wrapper():
... class A(object):
... print 'hello'
... 1+1
... pass
...
>>> dis.dis(wrapper)
2 0 LOAD_CONST 1 ('A')
3 LOAD_GLOBAL 0 (object)
6 BUILD_TUPLE 1
9 LOAD_CONST 2 (<code object A at 0x104b4adb0, file "<stdin>", line 2>)
12 MAKE_FUNCTION 0
15 CALL_FUNCTION 0
18 BUILD_CLASS
19 STORE_FAST 0 (A)
22 LOAD_CONST 0 (None)
25 RETURN_VALUE
>>> dis.dis(wrapper.__code__.co_consts[2])
2 0 LOAD_NAME 0 (__name__)
3 STORE_NAME 1 (__module__)
3 6 LOAD_CONST 0 ('hello')
9 PRINT_ITEM
10 PRINT_NEWLINE
4 11 LOAD_CONST 2 (2)
14 POP_TOP
5 15 LOAD_LOCALS
16 RETURN_VALUE
Now the class body appears; we can see the byte code that'll be executed when the class body is loaded.
Of note are the LOAD_NAME
and STORE_NAME
bytecodes executed for each class body; those retrieve the module name and store those as a new local name __module__
, so that your class will end up with a __module__
attribute once created.
The LOAD_LOCALS
bytecode then gathers all the local names produced in this 'function' and returns that to the caller, so that the BUILD_CLASS
bytecode can use that together with the 'A'
string and the object
bases tuple (created with BUILD_TUPLE
) can produce your new class object.
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