为什么类定义总是产生相同的字节码? [英] Why does a class definition always produce the same bytecode?
问题描述
说我做:
#!/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
现在我在类定义中添加一些语句:
Now I add some statements in the class definition:
#!/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
做什么新语句不会出现在新字节码中吗?
What don't the new statements appear in the new bytecode?
推荐答案
新语句存储在嵌套中字节码。您可以在反汇编中看到另一个代码对象已加载:
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
这与您的第一个示例相同;通过 wrapper .__ code __。co_consts
元组访问类主体,这是 LOAD_CONST
字节码所引用的;索引为 2
。
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.
值得注意的是 LOAD_NAME
和为每个类正文执行的 STORE_NAME
字节码;它们检索模块名称并将其存储为新的本地名称 __ module __
,这样您的类将以 __ module __
属性一旦创建。
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.
然后, LOAD_LOCALS
字节码收集此函数中产生的所有本地名称并返回给调用者,以便 BUILD_CLASS
字节码可以与'A'
字符串和 object
基元组(使用 BUILD_TUPLE
创建)可以生成新的类对象。
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.
这篇关于为什么类定义总是产生相同的字节码?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!