mypy:如何验证一个类型有多个超类 [英] mypy: how to verify a type has multiple super classes

查看:22
本文介绍了mypy:如何验证一个类型有多个超类的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想让 mypy 验证一个变量是从某个基类派生的,并且它有一个特定的 mixin.Union 仅验证该值是一种类型还是另一种类型.我需要检查该值是否为两种类型.

I would like mypy to verify that a variable is subclassed from a certain base class and that it also has a specific mixin. Union only verifies that the value is of one type or another. I need to check that the value is both types.

在这个例子中,我使用了一个关键字All"来展示我正在寻找的行为:

In the example, I'm making up a keyword "All" to demonstrate the behavior I'm looking for:

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 包装器.我的基类是基本的 Window 类.我需要的 Mixin 是 ControlHost,它将特定的窗口样式和功能添加到 Window 类以管理拥有子项,基本窗口不需要的东西.在创建子控件(例如 ComboBox)时,如果我提供给它的父窗口没有两个超类,我希望 mypy 调用我.

In case it's helpful, the reason I need this is I have my own win32 wrapper implemented in Python. My Base class is the basic Window class. My required Mixin is ControlHost which adds specific window styles and functions to the Window class to manage owning children, things that a basic window doesn't need. When creating child controls, like a ComboBox for example, I want mypy to call me out if the parent window I feed it doesn't have both super classes.

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

Also, I'm having an issue calling Window.init() from Control.init() because of a change of the parent's type. Here's abbreviated pseudo-code that illustrates the problem:

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

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

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

My work-around looks like this, but it doesn't allow mypy to catch type infractions:

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 ) )

推荐答案

您在这里主要寻找的是交叉点类型".

What you're basically looking for here are "intersection types".

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

Unfortunately, mypy (and any other PEP 484-compliant type checkers) do not support intersection types.

然而,有一些关于添加这种类型的讨论——你可以在 键入/PEP 484 问题跟踪器.

There is, however, some discussion about adding such a type -- you can find some discussion on the typing/PEP 484 issue tracker.

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

Unfortunately, my understanding (after talking to the mypy core devs yesterday) is that while they agree such a type would be useful, it's pretty low on their priority list: adding intersection types would require a substantial amount of careful thought and implementation work. (For example, working out what happens when unions, intersections, and type variables are combined.)

如果您尝试将您的示例/用例贡献给该线程,这可能会有所帮助——如果事实证明,大多数想要交集类型的人都希望将它用于特定的 mixin 或其他东西,那么 mypy 开发人员可能会认为一种不同的方式来支持该特定用例,而无需实现成熟的交集类型.

It would probably be helpful if you tried contributing your example/use case to that thread -- if it turns out most people who want intersection types want it for specifically mixins or something, it may be possible for the mypy devs to think of a different way to support that specific use case without implementing full-fledged intersection types.

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

As an interim measure, you can perhaps use Protocols: define a protocol containing the methods from both the base and mixin classes and use that as the function's type.

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

(That said, I imagine your window classes have a lot of methods, so this may not be such a feasible solution in your case.)

这篇关于mypy:如何验证一个类型有多个超类的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆