Как получить параметры функции из дис

Как получить список параметров функции в 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. Я хочу знать, как получить список параметров функции в порядке. В этом случае а и б

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

>>> 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 ответа

Решение

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]

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

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',)
Другие вопросы по тегам