将元类与多重继承结合使用的 TypeErrors

     2023-02-23     196

关键词:

【中文标题】将元类与多重继承结合使用的 TypeErrors【英文标题】:TypeErrors using metaclasses in conjunction with multiple inheritance 【发布时间】:2011-01-13 07:42:18 【问题描述】:

我有两个关于元类和多重继承的问题。第一个是:为什么我会得到类 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: Error when calling the metaclass bases Cannot create a consistent method resolution order (MRO) for bases object, Klass

第二个问题是:为什么super在这种情况下不起作用(如果我使用__init__而不是__new__super又起作用了):

class Metaclass(type):
    def __new__(self, name, bases, dict_):
        return super(Metaclass, self).__new__(name, bases, dict_)

class Klass(object):
    __metaclass__  = Metaclass

我明白了:

TypeError: Error when calling the metaclass bases type.__new__(X): X is not a type object (str)

我使用的是 Python 2.6。

【问题讨论】:

【参考方案1】:

你为什么要这样做?

class Derived(object, Klass):

类已经派生自对象。

class Derived(Klass):

这里是合理的吗。

【讨论】:

【参考方案2】:

第二个问题已经回答了两次,虽然__new__实际上是一个静态方法,而不是评论中错误声称的类方法...:

>>> class sic(object):
...   def __new__(cls, *x): return object.__new__(cls, *x)
... 
>>> type(sic.__dict__['__new__'])
<type 'staticmethod'>

第一个问题(正如有人指出的那样)与元类无关:您根本不能按照 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

MRO 保证最左边的碱基在最右边的碱基之前被访问 - 但它也保证在祖先中,如果 x 是 y 的子类,那么 x 在 y 之前被访问。在这种情况下,不可能同时满足这两个保证。当然,这些保证有一个很好的理由:没有它们(例如,在旧样式类中,它只保证方法解析中的左右顺序,不是子类约束)x 中的所有覆盖都将被忽略赞成y中的定义,这没有多大意义。想一想:首先从object 继承,然后从其他类继承意味着什么object 的(基本上不存在的;-)它的几个特殊方法的定义必须优先于其他类,导致其他类的覆盖被忽略?

【讨论】:

是有道理的,所以只要我不直接从对象继承(这实际上没有意义,但我想确保没有任何奇怪的事情发生)应该没问题:) 我想知道它是否保存到使用 new 而不使用 super. @nils,是的,__new__ 可以在没有 super 的情况下使用——除非在多重继承的复杂情况下。如果您喜欢复杂的多重继承,__new__ 会更谨慎。【参考方案3】:

对于第一个问题,请查看the description of MRO in python - 特别是“错误的方法解决顺序”部分。本质上,这与python不知道是使用对象还是使用Klass的方法有关。 (这与元类的使用无关。)

对于第二个问题,您似乎误解了__new__ 函数的工作原理。它不引用自身作为第一个参数——它引用被实例化的类的类型。所以你的代码应该是这样的:

class Metaclass(type):
    def __new__(cls, name, bases, dictn):
        return type.__new__(cls, name, bases, dictn)

【讨论】:

【参考方案4】:

对于第二个问题,您需要像这样将 self 传递给__new__

class Metaclass(type):
    def __new__(self, name, bases, dict_):
        return super(Metaclass, self).__new__(self, name, bases, dict_)

class Klass(object):
    __metaclass__  = Metaclass

我不记得为什么会这样,但我认为这是因为 type.__new__ 不是绑定方法,因此不会神奇地得到 self 参数。

【讨论】:

__new__ 是一个类方法,不要在那里使用 self ,这很混乱 是的,在我完成此操作的代码中,我使用了 cls 或类似的东西,但我遵循了原始海报使用的内容。

来自元类工厂的多重继承

】来自元类工厂的多重继承【英文标题】:Multiinheritancefrommetaclassesfactories【发布时间】:2012-02-1506:06:54【问题描述】:我希望SuperClass12继承自SuperClass1和SuperClass2:defgetClass1():classMyMetaClass1(type):def__new__(cls,name,bases,dct):printdct.get("A... 查看详情

涉及 Enum 的多重继承元类冲突

】涉及Enum的多重继承元类冲突【英文标题】:MultipleinheritancemetaclassconflictinvolvingEnum【发布时间】:2021-10-3010:34:41【问题描述】:我需要一个Enum类的双重继承,但也支持我自己的方法。这是上下文:importabcfromenumimportEnumclassMyFirst... 查看详情

元类冲突、多重继承、实例为父

】元类冲突、多重继承、实例为父【英文标题】:Metaclassconflict,multipleinheritance,andinstanceasparent【发布时间】:2011-11-2022:49:41【问题描述】:我一直在玩Python的黑暗艺术,有一些我想帮助理解的东西。给定一个类Foo,下面是我尝试... 查看详情

用于预定义类创建的元类与继承

】用于预定义类创建的元类与继承【英文标题】:Metaclassvsinheritanceforpredefinedclasscreation【发布时间】:2019-01-2603:48:58【问题描述】:我正在为一个程序编写一些代码,该程序将能够运行一些软件、读取输入/输出并在此过程中进... 查看详情

Peewee Model 和 QtCore QObject 的多重继承导致元类冲突

】PeeweeModel和QtCoreQObject的多重继承导致元类冲突【英文标题】:MultipleInheritancewithPeeweeModelandQtCoreQObjectcausingmetaclassconflict【发布时间】:2019-02-0519:58:35【问题描述】:首先我是python新手,这是我的第一篇文章,如果我在这里做错... 查看详情

我是不是将基类与超类一起继承以进行多重继承?

】我是不是将基类与超类一起继承以进行多重继承?【英文标题】:AmIinhertingbaseclassalongwithsuperclassformultipleinheritance?我是否将基类与超类一起继承以进行多重继承?【发布时间】:2014-08-0202:54:49【问题描述】:因此,我试图围绕... 查看详情

元类与 Django 中的 modelformset_factory 冲突

】元类与Django中的modelformset_factory冲突【英文标题】:metaclassconflictwithmodelformset_factoryinDjango【发布时间】:2011-12-1814:15:06【问题描述】:我正在使用Django模型继承来创建两个模型-WorkAttachmentPicture和WorkAttachmentAudioclassWorkAttachment(mo... 查看详情

结合 Qgraphics 和 sqlalchemy 时出现元类错误

】结合Qgraphics和sqlalchemy时出现元类错误【英文标题】:MetaclasserrorwhencombiningQgraphicsandsqlalchemy【发布时间】:2012-07-1705:54:24【问题描述】:我想使用sqlalchemy使QGraphicsItems持久化。轻松将Base类与PySide类结合起来会产生关于元类的错... 查看详情

Python 子类跟踪 - 元类与内置

】Python子类跟踪-元类与内置【英文标题】:PythonSubclassTracking-MetaclassesvsBuiltin【发布时间】:2012-03-2617:26:03【问题描述】:对于Django选项卡库,我创建了一个使用标记子类跟踪的架构。为此,我创建了一个基类,然后从中派生所... 查看详情

c++的探索路12继承与派生之高级篇--派生类与赋值运算符及多重继承(代码片段)

...程之继承与派生部分的最后一小部分,内容涉及派生类与赋值运算符以及多重继承。整体框架如下派生类和赋值运算符派生类的默认复制构造函数会调用基类的复制构造函数;同理,如果基类重载了赋值运算符“=... 查看详情

Django:从带有元的抽象类的多重继承

...问题描述】:我有一个模型继承自2个抽象模型,它们的元类中有属性。如何让它从两个父类继承元数据?好像只继承了先写的类的元数据。【问题讨论】:【参考方案1】:在Django中使用Python的多重继承的一般规则适用。这意味... 查看详情

抽象类与接口的区别

...象(接口没有构造方法,像太监没有小JJ)多态的区别:类与类:继承,单一继承(亲爹只有一个)类与接口:实现,单一、多重实现(可以认多个干爹)接口与接口:继承,单一、多重继承(可以认多个干爹)设计理念区别 查看详情

模型元类与模型形式元类有何不同?

】模型元类与模型形式元类有何不同?【英文标题】:HowismodelMetaclassdifferentfrommodelformMetaclass?【发布时间】:2021-12-1502:04:15【问题描述】:我想了解我们在模型中使用的元类。我在文档中找到了它。我记得在模型表单中也添加了... 查看详情

Python 元类与类装饰器

】Python元类与类装饰器【英文标题】:Pythonmetaclassesvsclassdecorators【发布时间】:2010-12-1906:13:25【问题描述】:Python元类和类装饰器之间的主要区别是什么?有什么我可以用一个做而另一个不能做的事情吗?【问题讨论】:【参... 查看详情

使用 python 元类和继承的问题

】使用python元类和继承的问题【英文标题】:Issueswithusingpythonmetaclassesandinheritence【发布时间】:2020-07-2610:15:25【问题描述】:我一直在为一个项目开发元类布局,其中所有类都使用自定义元类来加载他们定义的配置以及父类的... 查看详情

避免使用元类继承生成的类属性

】避免使用元类继承生成的类属性【英文标题】:Avoidinheritinggeneratedclassattributesusingmetaclass【发布时间】:2017-10-0709:34:25【问题描述】:我正在考虑使用元类自动将子类添加到父类以“链接”。但是,从父类继承这些属性会使事... 查看详情

Groovy 元类与 Java 8 的互操作性

】Groovy元类与Java8的互操作性【英文标题】:GroovymetaclassinteroperabilitywithJava8【发布时间】:2014-05-1009:12:54【问题描述】:简介:我正在开发一个名为awaitility的Java库,它也有一个Groovy扩展。在Java8之前,您可以像这样使用该库://... 查看详情

是否可以使用 Python 元类进行反向继承?

】是否可以使用Python元类进行反向继承?【英文标题】:IsitpossibletoinverseinheritanceusingaPythonmetaclass?【发布时间】:2016-11-1904:46:10【问题描述】:出于好奇,我很感兴趣是否可以编写一个元类,使父类的方法优先于子类的方法。我... 查看详情