Я хочу создать декоратор, который объединяет две функции и объединяет параметры из их подписи.Создание декоратора, который объединяет две функции без указания вызывающей сигнатуры исходной функции
Интерфейс Я хочу:
def f(a, b, c, d, e, f, g, h, i, j, k, l, m, n):
# I am using many parameters to explain the need of not
# needing to type the arguments again.
return a * b * c * d * e * f * g * h * i * j * k * l * m * n
@combines(f)
def g(o, p, *args, **kwargs):
return (o + p) * f(*args, **kwargs)
Это должно существенно привести:
def g(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p):
return (o + p) * (a * b * c * d * e * f * g
* h * i * j * k * l * m * n)
Причина я хочу это, потому что я не знаю, аргументы функции f
(я знаю но я не хочу набирать их снова, чтобы сделать его общим.)
Я не уверен, что мне нужно позвонить g
с *args
и **kwargs
, но я думаю, что это будет необходимо.
Это как далеко я получил:
import functools
import inspect
def combines(old_func):
old_sig = inspect.signature(old_func)
old_parameters = old_sig.parameters
def insert_in_signature(new_func):
new_parameters = inspect.signature(new_func).parameters
for new_parameter in new_parameters:
if new_parameter in old_parameters.keys():
raise TypeError('`{}` argument already defined'.format(new_parameter))
@functools.wraps(new_func)
def wrapper(*args, **kwargs):
return old_func(*args, **kwargs) * new_func(*args, **kwargs)
parms = list(old_parameters.values())
for arg, par in new_parameters.items():
if par.kind == inspect.Parameter.POSITIONAL_OR_KEYWORD:
parms.append(inspect.Parameter(arg, par.kind))
wrapper.__signature__ = old_sig.replace(parameters=parms)
return wrapper
return insert_in_signature
def f(a, b, c, d, e, f, g, h, i, j, k, l, m, n):
return a * b * c * d * e * f * g * h * i * j * k * l * m * n
@combines(f)
def g(o, p, *args, **kwargs):
return (o + p) * f(*args, **kwargs)
Это приводит к желаемому вызывающей подписи g
, но он не работает.
EDIT, поскольку сообщение об ошибке было предложено
Например: g(1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1)
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
<ipython-input-23-2775f64e1b3e> in <module>()
----> 1 g(1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1)
<ipython-input-18-3a843320e4e3> in wrapper(*args, **kwargs)
13 @functools.wraps(new_func)
14 def wrapper(*args, **kwargs):
---> 15 return old_func(*args, **kwargs) * new_func(*args, **kwargs)
16
17 parms = list(old_parameters.values())
TypeError: f() takes 14 positional arguments but 16 were given
если я затем следуют сообщение об ошибке и дать 14 аргументы g(1,1,1,1,1,1,1,1,1,1,1,1,1,1)
:
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
<ipython-input-24-052802b037a4> in <module>()
----> 1 g(1,1,1,1,1,1,1,1,1,1,1,1,1,1)
<ipython-input-18-3a843320e4e3> in wrapper(*args, **kwargs)
13 @functools.wraps(new_func)
14 def wrapper(*args, **kwargs):
---> 15 return old_func(*args, **kwargs) * new_func(*args, **kwargs)
16
17 parms = list(old_parameters.values())
<ipython-input-18-3a843320e4e3> in g(o, p, *args, **kwargs)
29 @combines(f)
30 def g(o, p, *args, **kwargs):
---> 31 return (o + p) * f(*args, **kwargs)
TypeError: f() missing 2 required positional arguments: 'm' and 'n'
So ясно, что моя реализация на самом деле не работает.
В какой конкретный способ она не работает? У вас есть пример _complete_, который могут попробовать другие люди? Покажи это. Есть ли ошибка? Покажи это_. – Useless
Спасибо за ваш комментарий, я добавил сообщение об ошибке. – johnbaltis