Python ABC 多重继承
Python ABC Multiple Inheritance
我认为代码会比我用文字更好地解释问题。这是 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: Error when calling the metaclass bases metaclass conflict: the metaclass of a derived class must be a (non-strict) subclass of the metaclasses of all its bases
我知道我可以创建一个 class 直接从我的接口 MyABC 继承,然后创建另一个 class 然后继承我创建的这个 class 和我的第三方模块 class。
我的问题是:是否有另一种更好、更正确的方法可以直接执行此操作,而无需为我的目的创建中间 class?
SomeClass
class 有自定义元class。您需要创建一个继承自 ABCMeta
和此自定义元class 的元class,然后将其用作MyClass
的元class。在不了解此自定义元class的更多信息的情况下,我无法确定在一般情况下执行此操作的正确方法,但它可能看起来像以下可能性之一:
class DerivedMeta(ABCMeta, type(SomeClass)):
pass
class DerivedMeta(type(SomeClass), ABCMeta):
pass
这不太可能,但您可能还需要重写一个或多个方法以确保正确的元class 交互。
您还可以将其他 class 的元class 设置为 ABCMeta,这样所有多碱基 class 的元class 都是 ABCMeta。
我在使用多重继承时遇到了类似的问题:
- a class 具有自定义元class
- a class 将 ABCMeta 作为元class
我为解决这个问题所做的是使我的自定义元class 派生自 ABCMeta。这似乎适用于所有情况。
这在所有情况下都对我有用。
class MyMeta(ABCMeta):
pass
而不是
class MyMeta(type):
pass
线程仍然在搜索结果的顶部,所以我想分享我的完整解决方案。
我 运行 在 Python 3.8 中尝试创建用于 PyQt5 小部件的抽象模板 class 时遇到了这个问题。我应用了@Kevin 的解决方案,首先创建了一个新元class。工作代码:
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()
# ...
我认为代码会比我用文字更好地解释问题。这是 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: Error when calling the metaclass bases metaclass conflict: the metaclass of a derived class must be a (non-strict) subclass of the metaclasses of all its bases
我知道我可以创建一个 class 直接从我的接口 MyABC 继承,然后创建另一个 class 然后继承我创建的这个 class 和我的第三方模块 class。
我的问题是:是否有另一种更好、更正确的方法可以直接执行此操作,而无需为我的目的创建中间 class?
SomeClass
class 有自定义元class。您需要创建一个继承自 ABCMeta
和此自定义元class 的元class,然后将其用作MyClass
的元class。在不了解此自定义元class的更多信息的情况下,我无法确定在一般情况下执行此操作的正确方法,但它可能看起来像以下可能性之一:
class DerivedMeta(ABCMeta, type(SomeClass)):
pass
class DerivedMeta(type(SomeClass), ABCMeta):
pass
这不太可能,但您可能还需要重写一个或多个方法以确保正确的元class 交互。
您还可以将其他 class 的元class 设置为 ABCMeta,这样所有多碱基 class 的元class 都是 ABCMeta。
我在使用多重继承时遇到了类似的问题:
- a class 具有自定义元class
- a class 将 ABCMeta 作为元class
我为解决这个问题所做的是使我的自定义元class 派生自 ABCMeta。这似乎适用于所有情况。
这在所有情况下都对我有用。
class MyMeta(ABCMeta):
pass
而不是
class MyMeta(type):
pass
线程仍然在搜索结果的顶部,所以我想分享我的完整解决方案。
我 运行 在 Python 3.8 中尝试创建用于 PyQt5 小部件的抽象模板 class 时遇到了这个问题。我应用了@Kevin 的解决方案,首先创建了一个新元class。工作代码:
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()
# ...