Class Score: def __init___(self,name): self.name = name 反编译后看到的字节码指令是: LOAD_BUILD_CLASS LOAD_CONST code object LOAD_CONST Score MAKE_FUNCTION 0 LOAD_CONST Score CALL_FUNCTION 2 STORE_NAME SCORE 为什么 MAKE_FUNCTION 0 LOAD_CONST Score #多了个这个,有啥用 CALL_FUNCTION 2
1. LOAD_BUILD_CLASS: 这是一个指令,用于加载内置的`__build_class__`函数。这个函数用于构建类。
2. LOAD_CONST code object: 这个指令将代码对象(即类的函数体)压入栈。这个代码对象包含了类体中的代码(包括方法等)。
3. LOAD_CONST 'Score': 这个指令将类名字符串'Score'压入栈。
4. MAKE_FUNCTION 0: 这个指令将之前压入的代码对象转换为一个函数。注意,这个函数实际上是类的命名空间执行函数。在Python中,类定义实际上是在执行一个代码块,然后将生成的局部命名空间传递给元类(默认是type)来创建类对象。
5. LOAD_CONST 'Score': 再次将类名字符串压入栈。这次是作为`__build_class__`函数的参数之一(类名)。
6. CALL_FUNCTION 2: 调用`__build_class__`函数,它需要两个参数:第一步中由MAKE_FUNCTION创建的函数,以及类名。
7. STORE_NAME Score: 将调用`__build_class__`返回的类对象存储到当前命名空间的名称'Score'下。
或者这样解释:
1. LOAD_BUILD_CLASS
加载内置的 __build_class__
函数到栈顶
这个函数负责实际创建类对象
2. LOAD_CONST <code object>
加载类体的代码对象(包含所有方法定义)
这个代码对象在编译时生成,包含了类中定义的所有函数
3. LOAD_CONST 'Score'
加载类名字符串 'Score' 到栈顶
这是类的名称,将作为第一个参数传递给 __build_class__
4. MAKE_FUNCTION 0
创建一个函数对象,该函数执行时会执行类体中的代码
参数 0
表示没有使用闭包变量
这个函数通常被称为"类构造函数"或"命名空间函数"
5. LOAD_CONST 'Score'
(额外的)
再次加载类名字符串 'Score' 到栈顶
这是为了作为第二个参数传递给 __build_class__
6. CALL_FUNCTION 2
调用栈顶的函数(__build_class__
),并传入 2 个参数
参数顺序:先压入的参数最后被使用
实际调用:__build_class__(func, name, ...)
func
: 由 MAKE_FUNCTION
创建的函数
name
: 类名 'Score'
7. STORE_NAME Score
将 __build_class__
返回的类对象存储到当前命名空间中
使用名称 'Score'
伪代码:
# 加载 __build_class__ 函数 __build_class__ = builtins.__build_class__ # 创建类构造函数 def class_constructor(): # 类体代码在这里执行 def __init___(self, name): self.name = name # 返回局部命名空间 return locals() # 创建类对象 Score_class = __build_class__(class_constructor, 'Score') # 存储到当前命名空间 Score = Score_class
在 Python 中,类定义实际上是在运行时执行的代码块,而不是编译时的静态声明。这个过程需要:
创建一个新的命名空间(字典)
在该命名空间中执行类体中的所有代码
使用这个命名空间来构建最终的类对象