在处理uncompyle6反编译错误时,我遇到了问题
尝试协调CPython程序集输出与Python
文档描述了MAKE_FUNCTION
。
Python来源:
def foo(x: 'an argument that defaults to 5' = 5):
return
Disassemby(xdis' s版本):
# 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中说:
在堆栈上推送新的函数对象。从下到上,消耗的堆栈必须由
组成
- argc&amp; 0xFF默认参数对象的位置顺序
- (argc&gt;&gt; 8)&amp; 0xFF对名称和默认参数,名称恰好在堆栈上的对象下方,仅用于关键字参数
- (argc&gt;&gt; 16)&amp; 0x7FFF参数注释对象
- 列出注释的参数名称的元组(仅当存在任何注释对象时)
在我看来,有一个注释对象,而不是两个。一个默认参数而不是位置参数。也
在第24位我们看到提到5,但这是在我们之后
MAKE_FUNCTION
。默认值与参数x
的关联在代码中是难以捉摸的。这里有一些优化吗?
我如何理解程序集作为Python源代码的准确表示?
注意:我看到这个代码至少在Python 3.1 - 3.5
中生成答案 0 :(得分:1)
以下是uncompyle6的上述内容。我并不完全确定mkfunc_annotate
的第一个参数被正确地称为pos_arg而不是默认值arg是正确的。
上面程序集中的一个细微点是LOAD_CONST
是一个元组(带有一个参数),这对于解析一个deparser(或者人)是很重要的,因为该函数是注释的。
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'