Как получить параметры функции из дис
Как получить список параметров функции в 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',)