了解 python 3.12 字节码的作用——在 GET_ITER 之后调用 0

问题描述 投票:0回答:1

我有这个Python函数和它翻译成的字节码:

Text code:

x = "-".join(str(z) for z in range(5))
assert x == "0-1-2-3-4"
print("Assert test case for generator_expression_in_join")


Disassembled code:

  0           0 RESUME                   0

  2           2 LOAD_CONST               0 ('-')
              4 LOAD_ATTR                1 (NULL|self + join)
             24 LOAD_CONST               1 (<code object <genexpr> at 0x1026abe30, file "<dis>", line 2>)
             26 MAKE_FUNCTION            0
             28 PUSH_NULL
             30 LOAD_NAME                1 (range)
             32 LOAD_CONST               2 (5)
             34 CALL                     1
             42 GET_ITER
             44 CALL                     0
             52 CALL                     1
             60 STORE_NAME               2 (x)

  3          62 LOAD_NAME                2 (x)
             64 LOAD_CONST               3 ('0-1-2-3-4')
             66 COMPARE_OP              40 (==)
             70 POP_JUMP_IF_TRUE         2 (to 76)
             72 LOAD_ASSERTION_ERROR
             74 RAISE_VARARGS            1

  4     >>   76 PUSH_NULL
             78 LOAD_NAME                3 (print)
             80 LOAD_CONST               4 ('Assert test case for generator_expression_in_join')
             82 CALL                     1
             90 POP_TOP
             92 RETURN_CONST             5 (None)

Disassembly of <code object <genexpr> at 0x1026abe30, file "<dis>", line 2>:
  2           0 RETURN_GENERATOR
              2 POP_TOP
              4 RESUME                   0
              6 LOAD_FAST                0 (.0)
        >>    8 FOR_ITER                15 (to 42)
             12 STORE_FAST               1 (z)
             14 LOAD_GLOBAL              1 (NULL + str)
             24 LOAD_FAST                1 (z)
             26 CALL                     1
             34 YIELD_VALUE              1
             36 RESUME                   1
             38 POP_TOP
             40 JUMP_BACKWARD           17 (to 8)
        >>   42 END_FOR
             44 RETURN_CONST             0 (None)
        >>   46 CALL_INTRINSIC_1         3 (INTRINSIC_STOPITERATION_ERROR)
             48 RERAISE                  1

我无法理解带有标签 44 的指令代表什么。我知道在指令 42 (

iter(range(5))
) 之后我的堆栈顶部有一个范围迭代器,但我不知道为什么会调用迭代器。

我正在尝试实现一个Python虚拟机,并且正在努力正确实现

CALL
操作码。我在提供的规范中没有看到任何帮助。

既然迭代器甚至不可调用,那么在迭代器上执行

CALL 0
背后的逻辑是什么?

python python-3.x virtual-machine bytecode
1个回答
0
投票

argc
是位置参数和命名参数的总和,不包括
self
(当
NULL
不存在时)。

这是一个电话:

28 PUSH_NULL 30 LOAD_NAME 1 (range) 32 LOAD_CONST 2 (5) 34 CALL 1
这是另一个:

24 LOAD_CONST 1 (<code object <genexpr> at 0x1026abe30, file "<dis>", line 2>) 26 MAKE_FUNCTION 0 ⋮ 42 GET_ITER 44 CALL 0
也就是说,您正在调用带有迭代器的生成器表达式 

self

请注意,该指令在 Python 3.13 中又有所不同。

© www.soinside.com 2019 - 2024. All rights reserved.