【问题标题】:mypy: how to verify a type has multiple super classesmypy:如何验证一个类型有多个超类
【发布时间】:2018-10-23 10:51:19
【问题描述】:

我希望 mypy 验证一个变量是某个基类的子类,并且它也有一个特定的 mixin。 Union 仅验证该值是否属于一种类型。我需要检查该值是否是两种类型。

在示例中,我创建了一个关键字“All”来展示我正在寻找的行为:

from typing import All

class Base ( object ):
    pass
class Mixin ( object ):
    pass

def assert_all ( x ):
    # type: ( All[Base,Mixin] ) -> None
    assert isinstance ( x, Base ) and isinstance ( x, Mixin )

class Child ( Mixin, Base ):
    pass

assert_all ( Child() )
try:
    assert_all ( Base() ) # !!! mypy should complain here
except AssertionError:
    pass
else:
    raise AssertionError ( 'assert inside of assert_all() should have fired' )
try:
    assert_all ( Mixin() ) # !!! mypy should complain here, too
except AssertionError:
    pass
else:
    raise AssertionError ( 'assert inside of assert_all() should have fired' )

如果它有帮助,我需要它的原因是我有自己的用 Python 实现的 win32 包装器。我的 Base 类是基本的 Window 类。我需要的 Mixin 是 ControlHost,它向 Window 类添加了特定的窗口样式和功能来管理拥有的孩子,这是基本窗口不需要的东西。在创建子控件(例如 ComboBox)时,如果我提供给它的父窗口没有两个超类,我希望 mypy 将我叫出来。

此外,由于父类型的更改,我在从 Control.init() 调用 Window.init() 时遇到问题。这是说明问题的简短伪代码:

class Window:
    def __init__ ( self, parent, .... ):
        # type: ( Optional[Window], .... )

class Control ( Window ):
    def __init__ ( self, parent, .... ):
        # type: ( Optional[ControlHost], .... )

我的解决方法看起来像这样,但它不允许 mypy 捕获类型违规:

class Control ( Control_mixin, Window ):
    ....

    def __init__ ( self, parent=None ):
        # type: ( Optional[ControlHost] ) -> None
        self.initStyle |= winapi.WS_CHILD|winapi.WS_CLIPSIBLINGS
        assert isinstance ( parent, Window )
        super ( Control, self ).__init__ ( cast ( Window, parent ) )

【问题讨论】:

    标签: mypy


    【解决方案1】:

    您在这里寻找的基本上是“交叉点类型”。

    很遗憾,mypy(以及任何其他符合 PEP 484 的类型检查器)不支持交集类型。

    不过,有一些关于添加这种类型的讨论——您可以在typing/PEP 484 issue tracker 上找到一些讨论。

    不幸的是,我的理解(在昨天与 mypy 核心开发人员交谈后)是,虽然他们同意这种类型很有用,但在他们的优先级列表中却很低:添加交集类型需要大量的仔细思考和实施工作。 (例如,计算联合、交集和类型变量组合时会发生什么。)

    如果您尝试将您的示例/用例贡献给该线程可能会有所帮助 - 如果事实证明大多数想要交叉类型的人都希望它用于专门的 mixins 或其他东西,那么 mypy 开发人员可能会认为在不实现成熟的交叉点类型的情况下支持特定用例的不同方式。


    作为临时措施,您或许可以使用Protocols:定义一个包含基类和mixin 类的方法的协议,并将其用作函数的类型。

    (也就是说,我想你的窗口类有很多方法,所以在你的情况下这可能不是一个可行的解决方案。)

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2012-06-19
      • 2020-05-08
      • 2014-02-10
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多