我有一个继承自 A 的 B 类:
class A():
def do_something(self, x):
"""Prints x."""
print(x)
class B(A):
def something_else(self, x):
print("This isn't the same.")
我想实现一些目标:
- 我希望
B.do_something
从A.do_something
继承文档字符串。我认为functools.wraps
是推荐的解决方案:对吗? 假设
A
的某些方法返回A
的实例。如果我从B
调用这些方法,我希望它们返回B
的实例。到目前为止,我正在手动重载每个函数。def method_of_A(self, *args, **kwargs): return A(super(self.__class__, self).method_of_A(*args, **kwargs))
可能有更好的方法 - 特别是考虑到我必须对大量类(class)执行此操作。是否有相同的方法来检查函数是否在
B
中定义,如果没有但在A
中可用,则将其装饰/包装以返回B 的实例
?编辑:我无法更改A
的代码库。- 是否有兼容 Py2 和 Py3 的解决方案?
非常感谢您的建议。
最佳答案
是的,您可以使用functools.wraps
复制函数名称和文档字符串。您可以使用self.__class__
返回当前类的实例。
class A(object):
def func(self):
return self.__class__()
class B(A):
@functools.wraps(A.func)
def func(self):
return super(B, self).func()
>>> b = B()
>>> obj = b.return_object()
>>> print type(obj)
"<class '__main__.B'>"
Is there same way to check if a function is defined within B and, if not but available in A, have it decorated / wrapped to return an instance of B?
您可以使用 metaclasses
来执行此操作,假设A
尚未使用您无法继承的自定义元类(就像它仅在 C 中定义并且尚未暴露给 python 一样)。在 python 2 和 3 中使用元类的方式略有不同。
class MetaB(type):
def __new__(cls, name, bases, attrs):
if A in bases:
for attr, value in A.__dict__.items():
if isinstance(value, types.FunctionType) and attr not in attrs:
new_func = MyMeta.make_wrapper_func(value)
attrs[attr] = new_func
return super(MetaB, cls).__new__(cls, name, bases, attrs)
@staticmethod
def make_wrapper_func(func):
@functools.wraps(func)
def _func(self, *args, **kwargs):
value = func(self, *args, **kwargs)
if isinstance(value, A):
value = self.__class__(value)
return value
return _func
class B(A):
__metaclass__ = MetaB
...
在 python 3 中,元类的使用方式略有不同
class B(A, metaclass=MetaB):
...
这假设您可以创建 B()
的对象只需传递 A()
的实例即可输入到它的构造函数(即 return self.__class__(value)
)。那只是一个猜测。我必须对你的对象有更多的了解才能知道如何翻译 A
反对B
对象,但一般方法是相同的。该解决方案也仅适用于常规类方法。它不适用于其他一些东西,例如 classmethods
和staticmethods
或其他类型的描述符对象。您当然可以让它适用于所有这些,您的元类只需要稍微复杂一点。
关于Python 继承、方法重载和装饰,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37892219/