我说:
#!/usr/bin/env python
# encoding: utf-8
class A(object):
pass
现在我把它拆开了:
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
现在我在类定义中添加一些语句:
#!/usr/bin/env python
# encoding: utf-8
class A(object):
print 'hello'
1+1
pass
我再次拆解:
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
新语句中出现的新语句不是什么?
答案 0 :(得分:17)
新语句存储在嵌套字节码中。您可以在反汇编中看到另一个代码对象已加载:
9 LOAD_CONST 1 (<code object A at 0x1004ebb30, file "test0.py", line 4>)
您需要检查该代码对象。这是因为类主体的执行方式与函数对象类似,然后调用产生的本地命名空间用于构成类成员。
演示:
>>> 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
这与您的第一个样本设置相同;通过wrapper.__code__.co_consts
元组访问类主体,这是LOAD_CONST
字节代码所指的内容;索引为2
。
现在我们可以添加一个类体:
>>> 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
现在出现了班级的身体;我们可以看到在加载类主体时执行的字节代码。
值得注意的是为每个类体执行的LOAD_NAME
和STORE_NAME
字节码;那些检索模块名称并将其存储为新的本地名称__module__
,以便您的类在创建后最终会得到__module__
属性。
LOAD_LOCALS
字节码然后收集在此功能中生成的所有本地名称&#39;并将其返回给调用者,以便BUILD_CLASS
字节码可以与'A'
字符串一起使用,而object
基本元组(使用BUILD_TUPLE
创建)可以产生新的类对象。