Я пытаюсь внести некоторую автоматизацию в сценарий, который пишу, и у меня возникают проблемы с вызовом функции, которая имеет параметры из другого модуля. Вот сценарий:

У меня есть два модуля: test.py и Strategies.py. У меня есть код, который генерирует список всех функций в Strategies.py. Из этого списка я использую getattr для выполнения каждой функции.

У меня проблемы с тем, что некоторые из моих функций имеют параметры. Я получаю следующую ошибку при использовании функции с аргументом x:

TypeError: buy_test_function() missing 1 required positional argument: 'x'

Чтобы сделать это как можно более понятным, вот соответствующий код:

call_method = strategy_names[0][y]
call_method = getattr(Strategies, call_method)()

Я знаю, что первая строка выше работает нормально. Я также знаю, что проблема связана с пустыми скобками в конце второй строки. Мне нужно найти способ динамически читать необходимые аргументы каждой функции и выполнять функцию с необходимыми аргументами в круглых скобках.

Я пытался использовать inspect.signature (), но он продолжает говорить мне, что объект не может быть вызван.

Я должен верить, что у Python есть элегантное решение этой проблемы, но мне не повезло с Google. Любая помощь приветствуется.

Спасибо!

0
thedavincicoder 3 Дек 2020 в 02:30

1 ответ

Лучший ответ

Предполагая, что функции в стратегиях не являются методами класса, и вы аннотировали типы функций в сигнатурах, вы можете создать экземпляры по умолчанию для типов классов, которые вы указали для аргументов, и передать их в качестве параметров:

from inspect import signature
call_method = strategy_names[0][y]
call_method = getattr(Strategies, call_method)
sig = signature(call_method)
call_method = getattr(Strategies, call_method)(*[param.annotation() for param in sig.parameters.values()])

См. Для справки:

>>> def test(x:int):
...    return x*2
>>> sig = signature(test)
>>> sig.parameters['x'].annotation
<class 'int'>
>>> sig.parameters['x'].annotation()
0
>>> test(*[param.annotation() for param in sig.parameters.values()])
0

Я также отмечу, что если вы можете заранее определить значения, которые хотите использовать в своих методах вызова для данного метода, а имена ваших функций в стратегиях уникальны, вы можете предварительно создать словарь, который сопоставляет имя функции с нужными аргументами. использовать:

args = {'test':[1]}
test(*args[test.__name__])
0
TheoretiCAL 2 Дек 2020 в 23:53