Python 继承、方法重载和装饰

标签 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_somethingA.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对象,但一般方法是相同的。该解决方案也仅适用于常规类方法。它不适用于其他一些东西,例如 classmethodsstaticmethods或其他类型的描述符对象。您当然可以让它适用于所有这些,您的元类只需要稍微复杂一点。

关于Python 继承、方法重载和装饰,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37892219/

相关文章:

python - 是否存在 "in"始终返回 true 的集合?

python - 覆盖 JWT,以便用户可以通过移动设备注册

c# - 继承自 System.Timers.ElapsedEventArgs 使单元测试更容易

python - 在 Python 中使用泛型动态键入子类

c++ - 我正在用 C++ 编写一个简单的继承程序,但出现了很多错误

ruby-on-rails - 过滤器出现之前的顺序是什么?

python - 正则表达式 - 替换带有加号或括号的单词

python - 使用 cElementTree 解析 XML

java - 跨包继承

python - 如何使用 qmark 语法和 oursql Python 库编写 MySQL LIKE 子句?