首页 > 解决方案 > 如果 mixin 的目标类继承自元类,如何键入提示 mixins?

问题描述

考虑以下类和 mixin:

class Target(ClassThatUsesAMetaclass):

    def foo(self):
        pass

class Mixin:

    def __init__(self):
        self.foo()  # type error: type checker doesn't know Mixin will have
                    # access to foo once in use.

class Combined(Mixin, Target):

    def __init__(self):
        Target.__init__(self)
        Mixin.__init__(self)

我试图避免上述场景中的类型检查器错误。一种选择是:

from typing import Protocol

class Fooable(Protocol):
    def foo(self): ...

class Mixin(Fooable):

    def __init__(self):
        self.foo()

本来会很好用,除了Target继承自使用元类的类,因此Combined不能同时继承TargetMixin。所以现在我正在尝试另一种方法,self注释Mixin

from typing import TYPE_CHECKING

if TYPE_CHECKING:
    from .this import Mixin, Target
    Mixin_T = type('Mixin_T', (Mixin, Target), {})


class Mixin:

    def __init__(self: Mixin_T):
        self.foo()  # No longer an error

class Combined(Mixin, Target):

    def __init__(self):
        Target.__init__(self)
        Mixin.__init__(self)  # Now this is an error: "Type[Mixin]" is not
                              # assignable to parameter "self"
                              # "Mixin" is incompatible with "Mixin_T"

那么除了使用之外我应该如何赢得这个# type: ignore呢?

标签: pythonmixinstype-hintingmetaclass

解决方案


除此之外,除了提供一些说明之外,上面几乎没有代码和一些错误概念使这个问题根本无法回答。

首先,您确定您是“从元类继承”吗?除非创建另一个元类,否则继承一个元类是没有意义的。您的片段显示您从假定的元类(没有给出代码)中继承,以创建 Target并尝试将它们Target用作普通类(非元类)的父类。这是没有意义的。

您可能只是混淆了这些术语,隐藏InheritFromMetaclass类实际上只是使用元类,而不是从它“继承”。那么您的问题根本与元类无关。

所以,片段中真正可见的问题是静态检查器没有“看到” self.fooMixin 类中的方法 - 你猜怎么着?没有方法- 检查器只是在你面前抛出一个冷酷的事实:虽然 Python 确实允许引用类中不可 用的方法和属性,但知道它将与其他具有这些属性的类一起使用,这不是好的设计并且容易出错。那种糟糕的设计静态类型检查存在被淘汰。self.fooMixin

所以,你需要的Mixin是一个抽象类的基础,并Foo作为一个抽象方法。(或者Mixin本身就是那个抽象类)。

如果 - 由于使用其他元类,由于元类冲突,您不能继承 Mixin abc.ABC,您必须:从 with 实际使用的元类创建一个组合元类,然后将InheritsFromMetaclassABCMeta用作元类Mixin - 或者只是创建一个存根foo方法按Mixin原样(这可能会引发NotImplementedError- 因此具有与抽象方法相同的行为,但实际上不必从它继承。

重要的部分是你在类体内的代码中访问的方法和属性必须存在于该类中,而不依赖于它的子类中存在的属性。

如果这不能解决您的问题,您需要提供更多数据 - 包括涉及您的实际元类的可重现的完整示例。(并且它可以通过组合上面提到的元类来解决)


推荐阅读