使用ABC,PolymorphicModel,django-models提供元类冲突

肥肠

到目前为止,SO答案上的所有其他答案都以完全相同的方式进行:构造您的元类,然后继承这些元类的“联接”版本,即

class M_A(type): pass
class M_B(type): pass
class A(metaclass=M_A): pass
class B(metaclass=M_B): pass

class M_C(M_A, M_B): pass
class C:(A, B, metaclass=M_C): pass

但是我不知道这些人所生活的世界是什么,他们正在构建自己的元类!显然,人们会使用其他库中的类,除非您对元编程有一个完美的了解,否则如何知道是否可以重写类的元类呢?(很明显,我还没有处理这些问题)。

我的问题是:

class InterfaceToTransactions(ABC):
    def account(self):
        return None
    ...

class Category(PolymorphicModel, InterfaceToTransactions):
    def account(self):
        return self.source_account
    ...

class Income(TimeStampedModel, InterfaceToTransactions):
    def account(self):
        return self.destination_account
    ...

当然哪个给了我错误:“元类冲突:派生类的元类必须是其所有基元元类的(非严格)子类”我尝试了上述给出的解决方案的许多变体,以下内容不起作用,给出相同的错误。

class InterfaceToTransactionsIntermediaryMeta(type(PolymorphicModel), type(InterfaceToTransactions)):
pass

class Category(PolymorphicModel, InterfaceToTransactions):
    __metaclass__ = InterfaceToTransactionsIntermediaryMeta
    ...

将任何内容放入类Meta函数中也不会。我已经阅读了有关此主题的所有其他问题,请不要简单地将其标记为重复。

-------------------接受解决方案后于1/8/18编辑-------

奇怪的是,如果我尝试使用这种新配置(我接受的配置)进行迁移,它会再次发出元类错误,但在运行时仍然可以使用。如果我注释掉元类部分,然后进行迁移和迁移,它将成功完成,但是每次迁移后,我都必须将其放回原处。

布宜诺斯艾利斯

如果您使用的是Python 3,则尝试错误使用派生的元类。

而且由于您得到的是“相同的错误”,而不是其他可能的,更细微的错误,所以我会说这是正在发生的事情。

尝试仅更改为:

class IntermediaryMeta(type(InterfaceToTransactions), type(PolymorphicModel)):
    pass

class Category(PolymorphicModel, InterfaceToTransactions, metaclass=IntermediaryMeta):
    ...

(至少保证ABCMeta类可以使用协同工作super,这足以使该类首先基于))

如果这会给您带来新的和改进的错误,则意味着由于多种动机之一,这些类中的一个或两个不能真正正确地进行协作。然后,要走的路是迫使不依赖ABCMeta的继承树这样做,因为它的作用几乎是美观的,在这种语言中,其他所有东西都是针对“同意成年人”的,如Python。

不幸的是,方法是使用各种暴力手段,从安全的“重新写入所有内容”到猴子补丁ABCMeta和“ InterfaceToTransactions”被定义为什么都不做的抽象方法。

如果您需要到达那里,并且需要一些帮助,请发布另一个问题。

抱歉-这实际上是使用元类的主要缺点。

本文收集自互联网,转载请注明来源。

如有侵权,请联系 [email protected] 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章