Python 3 注释的默认值代码生成

Code generation for Python 3 annotation with default value

在处理 uncompyle6 反编译错误时我遇到了问题 试图协调 CPython 汇编输出与 Python 文档描述 MAKE_FUNCTION.

Python 来源:

def foo(x: 'an argument that defaults to 5' = 5):
    return

Disassemby(xdis 的版​​本):

 # Argument count:    1
 # Kw-only arguments: 0
 # Number of locals:  1
 # Stack size:        1
 # Flags:             0x00000043 (NOFREE | NEWLOCALS | OPTIMIZED)
 # First Line:        1
 # Constants:
 #    0: 5
 #    1: 'an argument that defaults to 5'
 #    2: ('x',)
 #    3: <code object foo at 0x7f49115938a0, file "exec", line 1>
 #    4: 'foo'
 #    5: None
 # Names:
 #    0: foo
 1 0 LOAD_CONST                0 (5)
   3 LOAD_CONST                1 ('an argument that defaults to 5')
   6 LOAD_CONST                2 (('x',))
   9 LOAD_CONST                3 (<code object foo at 0x7f49115938a0, file "exec", line 1>)
  12 LOAD_CONST                4 ('foo')
  15 EXTENDED_ARG              2 (131072)
  18 MAKE_FUNCTION        131073 (1 positional, 0 name and default, 2 annotations)
  21 STORE_NAME                0 (foo)
  24 LOAD_CONST                5 (None)
  27 RETURN_VALUE

请注意,在偏移量 18 中,该值基本上是偏移量 19 (1) 处的 arg 值加上扩展的 arg 值。

括号内的解释是xdis的,可能不正确。 编辑:不仅正确,而且在偏移量 6 表示元组是必需的。

https://docs.python.org/3.4/library/dis.html#opcode-MAKE_FUNCTION 中说:

Pushes a new function object on the stack. From bottom to top, the consumed stack must consist of

  • argc & 0xFF default argument objects in positional order
  • (argc >> 8) & 0xFF pairs of name and default argument, with the name just below the object on the stack, for keyword-only parameters
  • (argc >> 16) & 0x7FFF parameter annotation objects
  • a tuple listing the parameter names for the annotations (only if there are any annotation objects)

在我看来只有一个注释对象,而不是两个。还有一个默认参数而不是位置参数。还 在偏移量 24 处,我们看到提到 5,但这是在我们有之后 MAKE_FUNCTION。默认值与参数 x 的关联在代码中是难以捉摸的。这里有某种优化?

我如何理解程序集作为 Python 源的准确表示?

注意:我看到此代码至少在 Python 3.1 - 3.5

中生成

下面是uncompyle6对上面的解析。我不完全确定 mkfunc_annotate 的第一个参数正确地称为 pos_arg 而不是默认值 arg.

是否正确

上面程序集中的一个细微之处是 LOAD_CONST 是一个元组(带有一个参数),这对于提示解析器(或人)很重要,因为该函数已被注释。

stmts
    sstmt
        stmt
            funcdef_annotate (2)
                 0. mkfunc_annotate (7)
                     0. pos_arg
                        expr
                            L.   1       0  LOAD_CONST            5  5
                     1. annotate_arg
                        expr
                                         3  LOAD_CONST               'an argument that defaults to 5'
                     2. annotate_tuple
                                     6  LOAD_CONST               ('x',)
                     3.              9  LOAD_CONST               '<code_object foo>'
                     4.             12  LOAD_CONST               'foo'
                     5.             15  EXTENDED_ARG     131074  '131072'
                     6.             18  MAKE_FUNCTION_A_2_1        '1 positional, 0 keyword pair, 2 annotated'
                 1. designator
                                21  STORE_NAME               'foo'