Python继承、方法重载和装饰

Python继承、方法重载和装饰,python,inheritance,Python,Inheritance,我有一个从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\u something从A.do\u something继承文档字符串。我认为functools.w

我有一个从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\u something
    A.do\u something
    继承文档字符串。我认为
    functools.wrapps
    是推荐的解决方案:对吗
  • 假设有一些
    A
    方法返回
    A
    的实例。如果我从
    B
    调用这些方法,我希望它们返回
    B
    的实例。到目前为止,我正在手动重载每个函数

    def method_of_A(self, *args, **kwargs):
        return A(super(self.__class__, self).method_of_A(*args, **kwargs))
    
    可能有更好的方法——特别是考虑到我必须为大量的课程做这件事。是否有相同的方法检查函数是否在
    B
    中定义,如果没有,但在
    a
    中可用,则对其进行修饰/包装以返回
    B
    的实例?编辑:我无法更改
    代码库

  • 是否有与Py2和Py3兼容的解决方案

非常感谢您的建议。

是的,您可以使用
functools.wrapps
复制函数名和docstring。您可以使用
self.\uuuu class\uuuu

class A(object):

    def func(self):
        return self.__class__()

class B(A):

    @functools.wraps(A.func)
    def func(self):
        return super(B, self).func()

在Python3中,元类的使用略有不同

class B(A, metaclass=MetaB):
    ...
这假设您可以创建
B()
类型的对象,只需将
A()
的实例传递给它的构造函数(即
返回self.\uu类\uuuuuu(值)
)。那只是猜测。我必须对你的对象多了解一些,才能知道如何将
a
对象转换为
B
对象,但一般方法是一样的。此解决方案也仅适用于常规类方法。它不适用于其他一些东西,如
classmethods
staticmethods
或其他类型的描述符对象。你当然可以让它为所有这些工作,你的元类只需要稍微复杂一点

假设A的某些方法返回A的实例。如果我从B调用这些方法,我希望它们返回B的实例。到目前为止,我正在手动重载每个函数

def method_of_A(self, *args, **kwargs):
    return A(super(self.__class__, self).method_of_A(*args, **kwargs))
使用类方法

class A(object):
    @classmethod
    def f(cls):
        return cls

当b(b的实例)调用f时,它将返回b。

谢谢-我应该更清楚,我不是在写
A
,而是在扩展别人的代码!我已经编辑了我的问题。我认为这在某些方面是过分的和错误的。首先-您知道,
isinstance
将始终返回给给定类的子类,不是吗?@jsbueno用户希望基于类继承动态创建具有单一用途(强制转换返回类型)的函数,以及在运行时之前可能不存在的函数。元类在这方面很好。唯一的另一个选择是类装饰器,与元类相比,它的复杂度不会降低,并且会有一些缺点。是的,我知道isinstance,你觉得它的哪个用法有问题吗?不,我认为你使用
isinstance(value,A)
来测试
B
A
的实例是可以的,在这种情况下,它总是会返回true-但这只是为了防止返回不返回
A
实例的值。我也没有尝试过OP不能更改
A
本身的代码这一事实,因此这种方法很好。@jsbueno。是的,我想如果返回值是用户不想包装的
A
的其他子类,那么在这些情况下isinstance可能是危险的。由于用户没有对
A
的控制权,我只是假设
A
不太可能返回
B
对象。可以执行类似“new_instance=type(self)(…)”这样的操作,但如果将
的docstring“prints x”
复制到执行
操作的函数中,则“不一样”
这不是一个坏主意吗?@Tadhgcdonald Jensen:如果它是一个简单的函数重载,返回的是类型B而不是类型a,那么B继承自a,不,这不是一个坏主意!这是我希望继承文档字符串的唯一情况。
class A(object):
    @classmethod
    def f(cls):
        return cls