Python之解决元类冲突

1,686 阅读1分钟

背景

子类多重继承时,多个父类之间拥有不同的元类,此时会产生错误:TypeError: metaclass conflict: the metaclass of a derived class must be a (non-strict) subclass of the metaclasses of all its bases。即父类ClassA中找不到抽象方法yyy,而yyy方法定义于父类ClassB的元类中,但ClassA的元类中并没有定义此方法。

class Meta1(type):
    def __new__(mcs, *args, **kwargs):
        return super(Meta1, mcs).__new__(mcs, *args, **kwargs)

class Meta2(type):
    def __new__(mcs, *args, **kwargs):
        return super(Meta2, mcs).__new__(mcs, *args, **kwargs)

class Body(metaclass=Meta1):
    pass

class Head(metaclass=Meta2):
    pass

class Human(Body, Head):
    pass

解决思路:

  • 多个父类中涉及的所有元类之间拥有继承关系
  • 自己构建一个元类,继承父类中涉及到的所有元类

实现

多个父类中涉及的所有元类之间拥有继承关系

class Meta1(type):
    def __new__(mcs, *args, **kwargs):
        return super(Meta1, mcs).__new__(mcs, *args, **kwargs)

# 变化部分:Meta2继承Meta1
class Meta2(Meta1):
    def __new__(mcs, *args, **kwargs):
        return super(Meta2, mcs).__new__(mcs, *args, **kwargs)

class Body(metaclass=Meta1):
    pass

class Head(metaclass=Meta2):
    pass

class Human(Body, Head):
    pass

执行到class Human代码行,解析后知道元类Meta2是Meta1的子类,创建Human类将会执行Meta2的new方法。

自己构建一个元类,继承父类中涉及到的所有元类

class Meta1(type):
    def __new__(mcs, *args, **kwargs):
        return super(Meta1, mcs).__new__(mcs, *args, **kwargs)

class Meta2(type):
    def __new__(mcs, *args, **kwargs):
        return super(Meta2, mcs).__new__(mcs, *args, **kwargs)

class Body(metaclass=Meta1):
    pass

class Head(metaclass=Meta2):
    pass

# 变化部分:新增元类继承所有涉及的元类
class CombineMeta(Meta1, Meta2):
    pass

# 设置元类
class Human(Body, Head, metaclass=CombineMeta):
    pass

或许元类Meta1和Meta2出于种种原因无法更改,这时可以自定义元类,继承这些互相独立的元类,从而避免元类冲突。

参考链接

Python3元类的多重继承