当使用 classmethod 动态更改子类中的方法时,如何动态更改方法的签名?
示例
import inspect
class ModelBase(object):
@classmethod
def method_one(cls, *args):
raise NotImplementedError
@classmethod
def method_two(cls, *args):
return cls.method_one(*args) + 1
class SubClass(ModelBase):
@staticmethod
def method_one(a, b):
return a + b
test = SubClass()
try:
print(inspect.signature(test.method_two))
except AttributeError:
print(inspect.getargspec(test.method_two).args)
我希望test.method_two
获得test.method_one
的签名。如何重写父类ModelBase
?
我读过Preserving signatures of decorated functions。在python3.4 +中,functools.wraps
有助于保留修饰函数的签名。我想将它应用于类方法。
使用functools.wraps
时,我需要指定装饰方法的名称。但是在这种情况下如何在classmethod
之外访问修饰方法?
from functools import wraps
class ModelBase(object):
@classmethod
def method_one(cls, *args):
raise NotImplementedError
@classmethod
def method_two(cls):
@wraps(cls.method_one)
def fun(*args):
return cls.method_one(*args) + 1
return fun
method_two
返回一个包装函数,但我必须将它与test.method_two()(*arg)
一起使用。这种方法不是直接的。
答案 0 :(得分:1)
如果这仅用于内省目的,您可以覆盖__getattribute__
上的ModelBase
,并且每次访问method_two
时,我们都会返回一个签名为method_one
的函数。< / p>
import inspect
def copy_signature(frm, to):
def wrapper(*args, **kwargs):
return to(*args, **kwargs)
wrapper.__signature__ = inspect.signature(frm)
return wrapper
class ModelBase(object):
@classmethod
def method_one(cls, *args):
raise NotImplementedError
@classmethod
def method_two(cls, *args):
return cls.method_one(*args) + 1
def __getattribute__(self, attr):
value = object.__getattribute__(self, attr)
if attr == 'method_two':
value = copy_signature(frm=self.method_one, to=value)
return value
class SubClass(ModelBase):
@staticmethod
def method_one(a, b):
return a + b
class SubClass2(ModelBase):
@staticmethod
def method_one(a, b, c, *arg):
return a + b
<强>演示:强>
>>> test1 = SubClass()
>>> print(inspect.signature(test1.method_two))
(a, b)
>>> test2 = SubClass2()
>>> print(inspect.signature(test2.method_two))
(a, b, c, *arg)