【发布时间】:2025-12-29 19:45:17
【问题描述】:
我有一个抽象类 @abstractmethods 它的 __init__ 和 __call__。原则上,类定义是这样的:
class Base(abc.ABC):
@abc.abstractmethod
def __init__(self, **params):
pass
@abc.abstractmethod
def __call__(self, *input):
pass
我想创建一个装饰器,将函数的关键字参数转换为__init__ 的参数,并将位置参数转换为__call__:所以如果
def func(a, b, *args, k=1, g=2, **kwargs):
pass # it does something
然后我想将我的 func 包装在一个装饰器中,该装饰器将像以下行一样输出
class Func(Base):
def __init__(self, k=1, g=2, **kwargs):
inspected_kwargs = ... # arguments of init in dictionary form
for argname, val in inspected_kwargs.items():
setattr(self, argname, val)
def __call__(self, a, b, *args):
inspected_args = ... # arguments of call in tuple form
return func(*inspected_args, **self.__dict__)
我曾尝试使用inspect,但我不确定如何将inspect.Signature 对象的参数注入回以创建函数。另外,我遇到了一些麻烦,因为当将本地方法添加到具有简单属性设置的函数内部的类时,返回该类时本地函数不再在范围内。
问题是:如何在函数内部创建一个类,其方法是基于函数输入可调用的签名定义的?
@编辑 要提供有关该想法的更多详细信息:
def decorator(function):
class Inner(Base):
pass
# non-existent functions ahead, just to convey the idea
# the exact way to do this is exactly the matter of this question
sig = inspect.get_signature(function)
init = create_from_signature(signature=sig.keyword_arguments(),
body="for name, val in sig.keyword_arguments():\nsetattr(self, name, val)")
call = create_from_signature(signature=sig.positional(),
body="return partial(func, **self.__dict__)")
Inner.__init__ = init
Inner.__call__ = call
# it would be nice if Inner class name would also depend on
# func name:
setattr(Inner, __name__, "_".join(function.__name__, "decorated"))
return Inner
def users_function(a, b, k=5):
# user's code; does whatever, for me it's a black box
return a * b / k
预期行为:
decorator(users_function)(k=10)(1, 2) == users_function(1, 2, k=10)
我为什么要这样做?因为这样就可以在输出的对象上调用Base 的方法,只需要知道关键字参数:
my_obj = decorator(users_function)(k=10)
my_obj.basemethod() # basemethod is implementd in Base class
【问题讨论】:
-
不确定我是否完全理解,您能否澄清您的最后一点。另外,您到底在哪里遇到问题?谢谢。
-
我只是不知道如何创建一个匹配来自签名对象的签名的函数。稍后将此方法添加到类中是另一个问题。
标签: python python-decorators inspect