Я не фанат магии таким образом.Я подозреваю, что у вас скорее есть основная проблема проектирования.
- оригинальный ответ и код, который был слишком неопределенным для удаленной проблемы -
Редактировать после понимания конкретной проблемы:
from inspect import getargspec
def can_call_effectively(f, args):
(fargs, varargs, _kw, df) = getattr(myfunc, 'effective_argspec', \
getargspec(myfunc))
fargslen = len(fargs)
argslen = len(args)
minargslen = fargslen - len(df)
return (varargs and argslen >= minargslen) or minargslen <= argslen <= fargslen
if can_call_effectively(myfunc, args)
myfunc(*args)
else:
fixit()
Все ваши декораторы, или, по крайней мере, те, которые вы хотите сделать прозрачными в отношении вызовов с помощью приведенного выше кода, должны установить'ffective_argspec 'в возвращаемом вызове.Очень явно, без магии.Чтобы достичь этого, вы можете украсить свои декораторы соответствующим кодом ...
Редактировать: больше кода, декоратор для прозрачных декораторов.
def transparent_decorator(decorator):
def wrapper(f):
wrapped = decorator(f)
wrapped.__doc__ = f.__doc__
wrapped.effective_argspec = getattr(f, 'effective_argspec', getargspec(f))
return wrapped
return wrapper
Используйте это на своем декораторе:
@transparent_decorator
def decorator(func):
"The most trivial (and common) decorator"
def wrapper(*args, **kwargs):
return func(*args, **kwargs)
return wrapper # line missing in example above
Теперь, если вы создадите myfunc1 - myfunc3, как указано выше, они будут работать точно так же, как и ожидалось.