我正在调试 python 脚本(python 不是我的首选语言),这是我第一次在 python 中使用元类。运行代码时出现元类冲突错误,如下所示。
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
在尝试解决它时,我注释掉了 MySQLMSoftware
中的元类声明,认为它是多余的,因为它继承自具有相同元类声明的类,但这导致:
TypeError: Error when calling the metaclass bases
module.__init__() takes at most 2 arguments (3 given)
任何见解、指导或方向将不胜感激。我一直在阅读有关 python 的元类实现的信息,但到目前为止还没有出现这个问题。
MSoftware.py
from abc import ABCMeta, abstractmethod
class MSoftware(object) :
__metaclass__ = ABCMeta
def __init__(self,name,spark=None,mysql=None):
self.name = name
...
MySQLMSoftware.py
from mouse import Mouse, MSoftware
from abc import ABCMeta, abstractmethod
class MySQLMSoftware(MSoftware): # Traceback always goes here
__metaclass__ = ABCMeta
MAX_ROWS = 30000000
def __init__(self,name,years,spark=None,mysql=None):
MSoftware.__init__(self,name,spark,mysql)
self.years = years
...
TTime.py
from mouse.Mouse import Mouse
from mouse.MySQLMSoftware import MySQLMSoftware
class TTime(MySQLMSoftware) :
DATABASE = "Database"
NAME = "table"
YEARS = [2014,2016]
def __init__(self,spark=None,mysql=None):
MySQLMSoftware.__init__(self,TTime.NAME,TTime.YEARS,spark,mysql)
...
主.py
import sys
from mouse.Mouse import Mouse
from mouse.TTime import TTime
...
最佳答案
问题是在选择元类时,python 会选择继承最多的版本。但是,您有两个相互冲突的元类(ABCMeta
和任何 MSoftware
拥有的)。
我认为 python3.x docs在这方面比 python2.x 文档稍微更正确:
The appropriate metaclass for a class definition is determined as follows:
- if no bases and no explicit metaclass are given, then type() is used
- if an explicit metaclass is given and it is not an instance of type(), > then it is used directly as the metaclass
- if an instance of
type()
is given as the explicit metaclass, or bases are defined, then the most derived metaclass is used
一个解决方案是创建一个新的元类,它是两者的混合:
class NewMeta(type(MSoftware), ABCMeta):
pass
在这种情况下,由于所有的元类都是MSoftware
的元类的“实例”,NewMeta
将被选中,因为它是最派生的元类,并且应该工作(前提是 MSoftware
的元类可以用于协作多重继承)。
这是一个动态创建 NewMeta
的示例,以通过一些虚拟类解决此问题:
class Meta1(type):
pass
class Meta2(type):
pass
class Class1(object):
__metaclass__ = Meta1
# TypeError!
# class Class2(Class1):
# __metaclass__ = Meta2
class Class2(Class1):
__metaclass__ = type('Class2Meta', (type(Class1), Meta2), {})
关于Python 元类冲突/类型错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38403795/