Как получить параметры функции из дис - PullRequest
0 голосов
/ 21 марта 2019

Как получить список параметров функции в python из объекта кода.

import xdis.std as dis
ops = list(dis.Bytecode("""def f(a, b):
    return 1"""))
print(ops)
code_obj = ops[0]
print(list(dis.Bytecode(code_obj.argval)))

Приведенный выше код использует модуль xdis для декомпиляции кода, который необходимо установить через pip.Однако объект кода - это обычный объект, который вы ожидаете от стандартного модуля dis в python.Я хочу знать, как получить список параметров функции в порядке.В этом случае a и b

Это вывод в интерактивном питоне -

>>> import xdis.std as dis
>>> ops = list(dis.Bytecode("""def f(a, b):
...     return 1"""))
>>> print(ops)
[Instruction(opname='LOAD_CONST', opcode=100, optype='const', inst_size=2, arg=0, argval=<code object f at 0x7a1a5c4f60, file "<disassembly>", line 1>, argrepr='<code object f at 0x7a1a5c4f60, file "<disassembly>", line 1>', has_arg=True, offset=0, starts_line=1, is_jump_target=False), Instruction(opname='LOAD_CONST', opcode=100, optype='const', inst_size=2, arg=1, argval='f', argrepr="'f'", has_arg=True, offset=2, starts_line=None, is_jump_target=False), Instruction(opname='MAKE_FUNCTION', opcode=132, optype=None, inst_size=2, arg=0, argval=0, argrepr='', has_arg=True, offset=4, starts_line=None, is_jump_target=False), Instruction(opname='STORE_NAME', opcode=90, optype='name', inst_size=2, arg=0, argval='f', argrepr='f', has_arg=True, offset=6, starts_line=None, is_jump_target=False), Instruction(opname='LOAD_CONST', opcode=100, optype='const', inst_size=2, arg=2, argval=None, argrepr='None', has_arg=True, offset=8, starts_line=None, is_jump_target=False), Instruction(opname='RETURN_VALUE', opcode=83, optype=None, inst_size=2, arg=None, argval=None, argrepr='', has_arg=False, offset=10, starts_line=None, is_jump_target=False)]
>>> code_obj = ops[0]
>>> print(list(dis.Bytecode(code_obj.argval)))
[Instruction(opname='LOAD_CONST', opcode=100, optype='const', inst_size=2, arg=1, argval=1, argrepr='1', has_arg=True, offset=0, starts_line=2, is_jump_target=False), Instruction(opname='RETURN_VALUE', opcode=83, optype=None, inst_size=2, arg=None, argval=None, argrepr='', has_arg=False, offset=2, starts_line=None, is_jump_target=False)]

Ответы [ 2 ]

1 голос
/ 21 марта 2019

Если у вас есть объект кода

def f(a, b, *, c=True):
    e = a + b
    if c:
        return a * e

code_obj = f.__code__

, тогда позиционные параметры -

code_obj.co_varnames[:code_obj.co_argcount]

# --> ('a', 'b')

, а параметры только для ключевых слов -

code_obj.co_varnames[code_obj.co_argcount : code_obj.co_argcount + code_obj.co_kwonlyargcount]

# --> ('c',)
0 голосов
/ 21 марта 2019

xdis не даст вам много полезных функций здесь.Это просто дает вам больше выходных данных объекта, которые вы теоретически могли бы испортить немного проще, чем обычный модуль dis.Но стандартный модуль говорит нам все, что нам нужно знать:

>>> from dis import dis
>>> def f(a, b):
...   return 1
...
>>> dis(f)
  2           0 LOAD_CONST               1 (1)
              2 RETURN_VALUE

Обратите внимание, что разборка включает в себя только два кода операции.LOAD_CONST помещает 1 в стек (среда выполнения cpython основана на стеке), а RETURN_VALUE возвращает функцию со значением в верхней части стека.Здесь нет ни упоминаний ни о a, ни b.И это имеет смысл.Они не используются!Байтовый код не касается аргументов функции.Он выдаст необходимые операции, чтобы поместить их в стек (где это необходимо):

>>> def f(a, b):
...   return a + b
...
>>> dis(f)
  2           0 LOAD_FAST                0 (a)
              2 LOAD_FAST                1 (b)
              4 BINARY_ADD
              6 RETURN_VALUE

Обратите внимание, что LOAD_FAST получает a и b и помещает их в стек для BINARY_ADD(который добавляет два верхних значения в стек и выводит результат).

Вы можете получить то, что хотите, используя __code__, а именно:

params_and_locals = f.__code__.co_varnames
num_args = f.__code__.co_argcount + f.__code__.co_kwonlyargcount
params = params_and_locals[:num_args]
...