如何动态更改子类中方法的签名? [英] How to dynamically change signatures of method in subclass?
问题描述
使用 classmethod 动态更改子类中的方法时,如何动态更改方法的签名?
When using classmethod to dynamic change the method in subclass, how to dynamic change signatures of method?
示例
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
?
I want test.method_two
to get the signatures of test.method_one
. How to rewrite parent class ModelBase
?
我已阅读有关保留装饰功能的签名。在python3.4 +中, functools.wraps
有助于保留修饰函数的签名。我想将其应用于类方法。
I have read about Preserving signatures of decorated functions. In python3.4 +, functools.wraps
helps to preserve signatures of decorated functions. I want to apply it to class method.
当使用 functools.wraps
时,我需要分配装饰方法的名称。但是在这种情况下,如何在 classmethod
之外访问修饰方法?
when uses functools.wraps
, I need to assign decorated method's name. But how to access decorated method outside classmethod
in this situation?
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)
一起使用。这种方法不是直接的。
method_two
returns a wrapped function, but I must use it with test.method_two()(*arg)
. This method is not directly.
推荐答案
如果这只是出于自省目的,则可以覆盖 __ getattribute __
。 ModelBase
上的code>,每次访问 method_two
时,我们返回一个具有<$签名的函数c $ c> method_one
If this is only for introspection purpose you could override __getattribute__
on ModelBase
and every time method_two
is accessed we return a function that has the signature of method_one
.
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)
这篇关于如何动态更改子类中方法的签名?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!