15

I think the code will explain the problem better than I can do with words. Here is the code in my_abc.py:

from abc import ABCMeta, abstractmethod

class MyABC(object):
    __metaclass__ = ABCMeta

    @abstractmethod
    def print(self):
        pass

Here is the code in 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')

When I try to run my_class.py I get:

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

I understand that I can create a class the inherits directly from my interface MyABC, and then create another class which then inherits from both this class which I created and my third party module class.

My question is: Is there another better and proper way of doing this directly without having to create an intermediate class for my purpose?

4

3 回答 3

9

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

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

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

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

于 2015-03-02T15:23:54.730 回答
5

线程仍然在搜索结果的顶部,所以我想分享我的完整解决方案。
我在尝试在 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()
# ...
于 2020-11-09T10:57:21.273 回答
0

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

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

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

我为解决这个问题所做的就是让我的自定义元类派生自 ABCMeta。这似乎适用于所有情况。

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

class MyMeta(ABCMeta):
  pass

代替

class MyMeta(type):
  pass
于 2019-04-03T13:00:00.350 回答