来自元类工厂的多重继承

     2023-02-23     128

关键词:

【中文标题】来自元类工厂的多重继承【英文标题】:Multi inheritance from metaclasses factories 【发布时间】:2012-02-15 06:06:54 【问题描述】:

我希望SuperClass12 继承自SuperClass1SuperClass2

def getClass1(): 
    class MyMetaClass1(type):
        def __new__(cls, name, bases, dct):
            print dct.get("Attr","")+"Meta1"
            return super(MyMetaClass1, cls).__new__(cls, name, bases, dct)
    return MyMetaClass1

def getClass2(): 
    class MyMetaClass2(type):
        def __new__(cls, name, bases, dct):
            print dct.get("Attr","")+"Meta2"
            return super(MyMetaClass2, cls).__new__(cls, name, bases, dct)
    return MyMetaClass2    

class SuperClass1():
    __metaclass__ = getClass1()
    def fun1(self):
        pass

class SuperClass2():
    __metaclass__ = getClass2()
    def fun2(self):
        pass

class MyClass1(SuperClass1):
    Attr = "MC1"

class MyClass2(SuperClass2):
    Attr = "MC2"

def getClass12(): 
    class myMultiMeta(getClass1(),getClass2()):
        pass
    return myMultiMeta

class SuperClass12(SuperClass1,SuperClass2):
#class SuperClass12(): gives no errors in class construction but then 
#fun1() and fun2() are not members of SuperClass12. 
    __metaclass__ = getClass12()

class MyClass12(SuperClass12):
    Attr = "MC12"

Instance = MyClass12()
Instance.fun1()
Instance.fun2()

很遗憾我遇到了这个错误:

TypeError: 调用元类基类时出错元类冲突:派生类的元类必须是其所有基类的元类的(非严格)子类

但我不明白为什么,因为我的派生类SuperClass12 的元类myMultiMeta 确实是其所有基类(SuperClass1,SUperClass2) 的元类(MyMetaClass1,MyMetaClass2) 的子类。

【问题讨论】:

【参考方案1】:

这是你想要的吗?

class MyMetaClass1(type):
    def __new__(cls, name, bases, dct):
        print dct.get("Attr","")+"Meta1"
        return super(MyMetaClass1, cls).__new__(cls, name, bases, dct)

class MyMetaClass2(type):
    def __new__(cls, name, bases, dct):
        print dct.get("Attr","")+"Meta2"
        return super(MyMetaClass2, cls).__new__(cls, name, bases, dct)

class SuperClass1():
    __metaclass__ = MyMetaClass1
    def fun1(self):
        pass

class SuperClass2():
    __metaclass__ = MyMetaClass2
    def fun2(self):
        pass

class MyClass1(SuperClass1):
    Attr = "MC1"

class MyClass2(SuperClass2):
    Attr = "MC2"

class MyMultiMeta(MyMetaClass1, MyMetaClass2):
    pass

class SuperClass12(SuperClass1, SuperClass2):
#class SuperClass12(): gives no errors in class construction but then 
#fun1() and fun2() are not members of SuperClass12. 
    __metaclass__ = MyMultiMeta

class MyClass12(SuperClass12):
    Attr = "MC12"

Instance = MyClass12()
Instance.fun1()
Instance.fun2()

运行:

vic@ubuntu:~/Desktop$ python test.py 
Meta1
Meta2
MC1Meta1
MC2Meta2
Meta1
Meta2
MC12Meta1
MC12Meta2
vic@ubuntu:~/Desktop$ 

【讨论】:

是的,这是所需的输出,现在我想知道为什么有些人定义返回元类的函数,就像我尝试使用 getClass1()、getClass2() 和 getClass12() 一样?我的代码有什么问题? @jimifiki,坦率地说 - 我不知道 :)。我只是试图清除你的这些函数的代码。【参考方案2】:

请记住,getClass1getClass2 返回元类的新实例。因此,当您设置__metaclass__ = getClass1() 时,它与myMultiMeta 继承的元类不同。

【讨论】:

是的,但是“元类工厂”对于多继承来说是一个糟糕的解决方案。 “元类工厂”有什么用? 这对很多事情都有好处,但是由于已经讨论过的问题,堆叠工厂不能以您的方式完成。更好的选择是将它变成一个可以抓取当前元类的类装饰器,并创建一个从它们继承的新元类,然后在您正在装饰的类上设置这个新元类。【参考方案3】:

感谢谁给了我一些答案,帮助了我:

def getClass12(): 
     class myMultiMeta(SuperClass1.__metaclass__,SuperClass2.__metaclass__):
         pass
     return myMultiMeta
 class SuperClass12(SuperClass1,SuperClass2):
     __metaclass__ = getClass12()

是一个不错的解决方案!

【讨论】:

【参考方案4】:

正如 Michael Merickel 所指出的,getClass() 函数需要在每次调用时返回相同的对象才能使您的继承工作。仅仅相同的类是不够的。这是一种方法,滥用一个类使其表现得像你的getClass() 函数。由于类定义只执行一次,MyMetaClass1 返回时始终是同一个对象。

class getClass1(object):
    class MyMetaClass1(type):
        def __new__(cls, name, bases, dct):
            print dct.get("Attr","")+"Meta1"
            return super(MyMetaClass1, cls).__new__(cls, name, bases, dct)
    class __metaclass__(type):
        def __call__(cls):
            return cls.MyMetaClass1

你也可以这样做,使用一个真实的函数并滥用一个可变的默认参数来缓存类实例:

def getClass1(cls=[]):
    if not cls:
        class MyMetaClass1(type):
            def __new__(cls, name, bases, dct):
                print dct.get("Attr","")+"Meta1"
                return super(MyMetaClass1, cls).__new__(cls, name, bases, dct)
        cls.append(MyMetaClass1)
    return cls[0]

您会注意到这里反复出现的主题:滥用 Python 功能。 :-) 这通常表明您正在做一些可能以其他方式做得更好的事情。例如,您为什么要使用工厂,而不是仅仅以正常方式定义类?我见过类工厂有一些用处,但我认为我从未在野外见过元类工厂。

【讨论】:

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

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

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

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

unittest 模拟和多重继承:TypeError:元类冲突

】unittest模拟和多重继承:TypeError:元类冲突【英文标题】:unittestmockandmultipleinheritance:TypeError:metaclassconflict【发布时间】:2018-06-0609:32:57【问题描述】:我有一个包,它的依赖项不是pip可安装的。为了能够构建文档,我正在尝... 查看详情

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

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

来自两个派生类的多重继承

】来自两个派生类的多重继承【英文标题】:MultipleInheritancefromtwoderivedclasses【发布时间】:2010-09-2006:14:00【问题描述】:我有一个作为接口的抽象基类。我有两个“集”派生类,它们实现了抽象类的一半。(一个“set”定义了... 查看详情

来自两个抽象类的多重继承 (Qt)

】来自两个抽象类的多重继承(Qt)【英文标题】:Multipleinheritancefromtwoabstractclasses(Qt)【发布时间】:2014-05-0312:50:24【问题描述】:我有我的抽象类(A),它描述了一次实地考察和Qt基类QGraphicsItem,它描述了用于控制项目的Qt函数。我... 查看详情

阻止继承的思路,屏蔽友元类

来自万一:http://www.cnblogs.com/del/archive/2008/01/16/1041446.html--------------------------------------------------------------------------------------- //下面说的数据成员不仅仅指方法TMyClass=class(TObject)  查看详情

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

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

带有接口的 C++ 多重继承?

...【发布时间】:2011-03-0212:22:55【问题描述】:大家好,我来自Java背景,在多重继承方面遇到困难。我有一个名为IView的接口,它具有init()方法。我想派生一个名为PlaneViewer的新类,实现上述接口并扩展另一个类。(QWidget)。我的实... 查看详情

C# 应该有多重继承吗? [关闭]

...东西在接口不合适的情况下,组合是一个很好的替代品我来自C++背景,怀念多重继承的强大和优雅。尽管它并不适合所有软件设 查看详情

使用元类实现工厂设计模式

】使用元类实现工厂设计模式【英文标题】:Implementingthefactorydesignpatternusingmetaclasses【发布时间】:2011-01-2711:16:53【问题描述】:我发现了很多关于元类的链接,其中大多数都提到它们对于实现工厂方法很有用。你能告诉我一个... 查看详情

从类“UIApplication”和“FBSDKApplicationDelegate”的多重继承

...【发布时间】:2017-11-1115:03:26【问题描述】:我正在使用来自facebook网站https://developers.facebook.com/docs 查看详情

为啥元类不能访问由元类定义的类的子类继承的属性?

】为啥元类不能访问由元类定义的类的子类继承的属性?【英文标题】:Whydoesametaclassnothaveaccesstotheattributesinhereitedfromasubclassofaclassdefinedbythemetaclass?为什么元类不能访问由元类定义的类的子类继承的属性?【发布时间】:2015-07-06... 查看详情

使用元类而不是工厂模式

】使用元类而不是工厂模式【英文标题】:Usingmetaclassesinsteadoffactorypattern【发布时间】:2021-12-2712:26:01【问题描述】:假设我们有一个具有不同CarTypes的实体(Car):classCarTypes(Enum):SUV=\'suv\'SPORT=\'sport\'@dataclassclassCar:id:UUIDtype:CarTy... 查看详情

python元类继承问题

】python元类继承问题【英文标题】:pythonmetaclassinheritanceissue【发布时间】:2016-07-1902:12:53【问题描述】:我有一个有点奇怪的元类问题。我正在使用元类动态创建一个继承自另一个超类的“兄弟”类,并将其分配为原始类的属... 查看详情

python 3.2插件工厂:从类/元类实例化

】python3.2插件工厂:从类/元类实例化【英文标题】:python3.2pluginfactory:instantiationfromclass/metaclass【发布时间】:2011-08-2121:35:18【问题描述】:我正在从这里的信息中复制:Metaclassnotbeingcalledinsubclasses我的问题是我无法使用此类注... 查看详情

python中的元类作用?

元类是类的类。类定义类的实例(即对象)的行为,而元类定义类的行为。类是元类的实例。虽然在Python中你可以对元类使用任意可调用对象(如Jerub演示),但是更好的方法是使其成为实际的类。type是Python中常见的元类。type... 查看详情

如何记录从元类继承的方法?

】如何记录从元类继承的方法?【英文标题】:HowcanIdocumentmethodsinheritedfromametaclass?【发布时间】:2021-10-2305:45:22【问题描述】:考虑以下元类/类定义:classMeta(type):"""Apythonmetaclass."""defgreet_user(cls):"""Printafriendlygreetingidentifyingthecla... 查看详情