猿问

为什么反汇编一个Python类定义会显示两个相同的类名的LOAD_CONST?

我想知道为什么PythonLOAD_CONST在定义一个类时会两次使用相同的值(类名)。当我运行这段代码时:


from dis import dis


dis("class A(): pass")

这是我得到的输出:


  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

正如您在第 3 行和第 5 行中看到的,有两个LOAD_CONST带有类名。


LOAD_CONST如果类名已经加载,为什么还要使用相同的数据创建第二个呢?MAKE_FUNCTION这和他们之间有什么关系吗LOAD_CONST?


我在 python 3.7.4 64 位上运行它


湖上湖
浏览 78回答 1
1回答

慕姐4208626

 CPython 中的类型创建暂时使用函数对象作为类主体。第一个“A”用于该函数的名称。第二个“A”用于类名。帖子的其余部分详细解释了这个反汇编: 0 LOAD_BUILD_CLASS压builtins.__build_class__入堆栈。随后由 CALL_FUNCTION 调用它来构造一个类。 2 LOAD_CONST               0 (<code object A at 0xCAFEF00D, file "<dis>", line 1>)将代码 obj 压入堆栈(这实际上包含解析的类块 - 继续阅读) 4 LOAD_CONST               1 ('A')将“A”压入堆栈 6 MAKE_FUNCTION            0将新的函数对象压入堆栈。此操作还消耗堆栈上的前两个内容(此函数的代码 obj 及其限定名称) 8 LOAD_CONST               1 ('A')再次将“A”压入堆栈,以便可以用作 中的第二个参数builtins.__build_class__,即类名。10 CALL_FUNCTION            2使用堆栈中的“A”和一个函数对象,调用__build_class__(<func>, 'A'). 操作名称后面的 2 指的是所咀嚼的位置参数的数量。最右边的位置参数位于堆栈顶部,因此它们将是:类名'A',然后是 MAKE_FUNCTION 中剩余的 obj,它体现了类定义。这些参数的“下面”是可调用的__build_class__,这个操作也消耗它。未提供任何接受的可选参数__build_class__(func, name, /, *bases, [metaclass], **kwds) -> class。12 STORE_NAME               0 (A)A = <top of stack>,本质上是在命名空间中绑定新创建的类 obj14 LOAD_CONST               2 (None)RETURN_VALUE 将返回堆栈顶部,但类语句 exec 不需要返回值,因此None在返回之前加载。16 RETURN_VALUE我们完成了。
随时随地看视频慕课网APP

相关分类

Python
我要回答