Python ABC多重继承

moe*_*dol 4 python metaclass multiple-inheritance python-2.7 urwid

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

from abc import ABCMeta, abstractmethod

class MyABC(object):
    __metaclass__ = ABCMeta

    @abstractmethod
    def print(self):
        pass
Run Code Online (Sandbox Code Playgroud)

这是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')
Run Code Online (Sandbox Code Playgroud)

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

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

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

我的问题是:是否有另一种更好,更适当的方法直接执行此操作,而无需为我的目的创建中间类?

Rob*_*rto 7

线程仍然位于搜索结果的顶部,所以我想分享我的完整解决方案。
当我尝试在 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()
# ...
Run Code Online (Sandbox Code Playgroud)


Kev*_*vin 5

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

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

class DerivedMeta(type(SomeClass), ABCMeta):
    pass
Run Code Online (Sandbox Code Playgroud)

不太可能,但可能还需要重写一种或多种方法以确保正确的元类交互。