Python 将元类与多重继承结合使用时出现的类型错误
我有两个关于聚合元类和多重继承的问题。第一个问题是:为什么类Python 将元类与多重继承结合使用时出现的类型错误,python,multiple-inheritance,python-2.x,metaclass,Python,Multiple Inheritance,Python 2.x,Metaclass,我有两个关于聚合元类和多重继承的问题。第一个问题是:为什么类Derived会出现TypeError,而Derived2却没有 class Metaclass(type): pass class Klass(object): __metaclass__ = Metaclass #class Derived(object, Klass): pass # if I uncomment this, I get a TypeError class OtherClass(object): p
Derived
会出现TypeError,而Derived2
却没有
class Metaclass(type): pass
class Klass(object):
__metaclass__ = Metaclass
#class Derived(object, Klass): pass # if I uncomment this, I get a TypeError
class OtherClass(object): pass
class Derived2(OtherClass, Klass): pass # I do not get a TypeError for this
确切的错误消息是:
TypeError:调用元类基时出错
无法为基本对象Klass创建一致的方法解析顺序(MRO)
第二个问题是:super
在这种情况下为什么不起作用(如果我使用\uuuuuu init\uuuuuuuuuuuu
而不是\uuuuuu new\uuuuuuuu
,super
再次起作用):
我得到了:
TypeError:调用元类基类型时出错。\uuuu new\uuuux:
X不是类型对象(str)
我正在使用Python2.6。对于第一个问题,请看一看“坏方法解析顺序”部分。本质上,这是因为python不知道是使用object还是Klass的方法。(这与元类的使用无关。) 对于第二个问题,您似乎误解了
\uuuu new\uuu
函数的工作原理。它不把对自身的引用作为第一个参数,而是引用被实例化的类的类型。因此,您的代码应该如下所示:
class Metaclass(type):
def __new__(cls, name, bases, dictn):
return type.__new__(cls, name, bases, dictn)
class Metaclass(type):
def __new__(self, name, bases, dict_):
return super(Metaclass, self).__new__(self, name, bases, dict_)
class Klass(object):
__metaclass__ = Metaclass
对于第二个问题,您需要将self传递给
\uuuu new\uuuu
,如下所示:
class Metaclass(type):
def __new__(cls, name, bases, dictn):
return type.__new__(cls, name, bases, dictn)
class Metaclass(type):
def __new__(self, name, bases, dict_):
return super(Metaclass, self).__new__(self, name, bases, dict_)
class Klass(object):
__metaclass__ = Metaclass
我一时想不起为什么会这样,但我想这是因为
类型。
不是一个绑定方法,因此不会神奇地获得自论证。第二个问题已经被很好地回答了两次,尽管\u new\u
实际上是一个静态方法,不是注释中错误声明的classmethod…:
>>> class sic(object):
... def __new__(cls, *x): return object.__new__(cls, *x)
...
>>> type(sic.__dict__['__new__'])
<type 'staticmethod'>
类sic(对象):
... def uuu new uuuu(cls,*x):返回对象。uuu new uuuuu(cls,*x)
...
>>>类型(原文如此)
第一个问题(正如有人指出的)与元类无关:你不能按照B是A的子类的顺序从任意两个类A和B进行乘法继承。例如:
>>> class cis(sic): pass
...
>>> class oops(sic, cis): pass
...
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: Error when calling the metaclass bases
Cannot create a consistent method resolution
order (MRO) for bases sic, cis
>>类别CI(sic):通过
...
>>>类oops(sic、cis):通过
...
回溯(最近一次呼叫最后一次):
文件“”,第1行,在
TypeError:调用元类基时出错
无法创建一致的方法解析
基础sic、cis的订单(MRO)
MRO保证最左边的碱基在最右边的碱基之前访问,但它也保证在祖先中,如果x是y的子类,那么x在y之前访问。在这种情况下,不可能同时满足这两种保证。当然,这些保证有一个很好的理由:如果没有它们(例如,在旧式类中,只保证方法解析中的左右顺序,而不是子类约束),x中的所有重写都将被忽略,而代之以y中的定义,这没有多大意义。想想看:首先从对象
继承,然后从其他类继承意味着什么?对象的几个特殊方法的定义(基本上不存在;-)必须优先于其他类的定义,从而导致忽略其他类的重写?为什么要这样做
class Derived(object, Klass):
Klass已经从object派生
class Derived(Klass):
在这里是合理的。
\uuuu new\uuuuuu
是一个类方法,不要在那里使用self,这很令人困惑是的,在我使用的代码中,我使用了cls
或类似的东西,但我遵循了原始海报使用的。有意义,只要我不直接从对象继承(这实际上没有什么意义,但我想确定没有什么奇怪的事情发生)应该没问题:)我想知道使用new而不使用super是否可以保存。@nils,是的\uuuuuuu new\uuuuuu
可以使用w/osuper
——除非在多重继承的复杂情况下。如果你陷入了复杂的多重继承,\uuuuuuuuuuuuuuuuuuuuuuu
更为谨慎。