Python ABC多重继承

时间:2015-03-01 21:07:51

标签: python python-2.7 multiple-inheritance metaclass urwid

我认为代码会比用文字更好地解释问题。以下是my_abc.py中的代码:

from abc import ABCMeta, abstractmethod

class MyABC(object):
    __metaclass__ = ABCMeta

    @abstractmethod
    def print(self):
        pass

以下是my_class.py

中的代码
from my_abc import MyABC
from third_party_package import SomeClass

class MyClass(MyABC, SomeClass):
    def __init__(self):
        super(MyClass, self).__init__()

    def print(self):
        print('Hello ABC')

当我尝试运行my_class.py时,我得到:

  

TypeError:调用元类基类元类冲突时出错:派生类的元类必须是其所有基类的元类的(非严格)子类

据我所知,我可以创建一个直接从我的接口MyABC继承的类,然后创建另一个类,然后继承自我创建的这个类和我的第三方模块类。

我的问题是:是否有另一种更好,更正确的方法直接这样做,而不必为我的目的创建一个中间类?

3 个答案:

答案 0 :(得分:4)

SomeClass类有一个自定义元类。您需要创建一个继承自ABCMeta和此自定义元类的元类,然后将其用作MyClass的元类。在不了解更多有关此自定义元类的情况下,我无法确定在一般情况下执行此操作的正确方法,但它可能看起来像以下其中一种:

class DerivedMeta(ABCMeta, type(SomeClass)):
    pass

class DerivedMeta(type(SomeClass), ABCMeta):
    pass

不太可能,但您可能还需要覆盖一个或多个方法以确保正确的元类交互。

答案 1 :(得分:0)

您还可以将另一个类的元类设置为ABCMeta,以便所有多个基类的元类都是ABCMeta。

在使用多重继承时,我遇到类似的问题:

  • 具有自定义元类的类
  • 具有ABCMeta作为元类的类

我要做的就是使我的自定义元类派生自ABCMeta。这似乎在所有情况下都有效。

这在所有情况下都对我有用。

class MyMeta(ABCMeta):
  pass

代替

class MyMeta(type):
  pass

答案 2 :(得分:0)

线程仍位于搜索结果的顶部,所以我想分享我的完整解决方案。
尝试在Python 3.8中创建旨在用于PyQt5小部件的抽象模板类时遇到了这个问题。我应用了@Kevin的解决方案,首先创建了一个新的元类。工作代码:

from abc import ABC, ABCMeta
from PyQt5.QtWidgets import QWidget, QLabel


class QABCMeta(ABCMeta, type(QWidget)):
    """Create a meta class that combines ABC and the Qt meta class"""
    pass


class TcWidget(ABC, metaclass=QABCMeta):
    """Abstract class, to be multi-inherited together with a Qt item"""
    pass


class TcLabel(QLabel, TcWidget):
    """Label that shows a value"""
    pass


# ...
label = TcLabel()
# ...