【问题标题】:Let mypy warn about equality checks of variables with different type让 mypy 警告不同类型的变量的相等性检查
【发布时间】:2018-09-01 05:48:16
【问题描述】:

mypy --strict 允许以下最小示例没有任何错误:

a: int = 1
b: str = '1'

if a == b:
    pass
else:
    pass

是否有可能让它发出关于if a == b: 行的错误(或至少是警告)?

【问题讨论】:

    标签: python-3.x types static-typing mypy


    【解决方案1】:

    编辑:下面我的原始答案描述了如何通过编写自定义 mypy 插件来实现这一点。

    但是,as of mypy 0.700,现在可以通过--strict-equality 标志直接执行此操作。请注意,在撰写本文时,默认情况下此标志并未通过 --strict 标志启用。

    例如在上面的原程序上运行mypy会产生如下错误:

    test.py:4: error: Non-overlapping equality check (left operand type: "int", right operand type: "str")
    

    您可以在 mypy 命令行标志文档的 Miscellaneous strictness options 部分底部附近找到有关此标志的更多详细信息。


    这可以使用(目前处于试验阶段且未记录的)插件 API 来实现。

    简而言之,在项目中的某处添加以下文件:

    from typing import Callable, Optional, Type
    from mypy.plugin import MethodContext, Plugin
    from mypy.meet import is_overlapping_types
    
    class StrictEqualityPlugin(Plugin):
        def get_method_hook(self, fullname: str) -> Optional[Callable[[MethodContext], Type]]:
            if fullname.endswith('__eq__') or fullname.endswith('__ne__'):
                return strict_check_callback
    
    def strict_check_callback(ctx: MethodContext) -> Type:
        if len(ctx.arg_types) == 1 and len(ctx.arg_types[0]) == 1:
            # Note: Expressions of the form 'base_type == arg_type' get
            # translated into `base_type.__eq__(arg_type)`.
            base_type = ctx.type
            arg_type = ctx.arg_types[0][0]
    
            # Two types are overlapping if one of the types could potentially be the
            # same as or a subtype of the other.
            #
            # If you want something even stricter, add `from mypy.sametypes import is_same_type`
            # up at the top and call `is_same_type` instead of `is_overlapping_types`.
            if not is_overlapping_types(base_type, arg_type):
                ctx.api.msg.warn(
                    "The left and right operands have disjoint types ({} and {})".format(
                        ctx.api.msg.format(base_type),
                        ctx.api.msg.format(arg_type),
                    ), 
                    ctx.context)
        return ctx.default_return_type
    
    def plugin(mypy_version: str) -> Plugin:
        return StrictEqualityPlugin
    

    假设这个文件的名字是strict_equality_plugins.py

    然后,在项目的顶层中,创建一个mypy.ini 文件。该文件至少应包含以下内容:

    [mypy]
    plugins = ./path/to/strict_equality_plugins.py
    

    然后,在你的根项目中运行 mypy 会产生如下错误:

    foo.py:1:警告:左右操作数的类型不相交(“int”和“str”)

    免责声明: mypy 项目的插件 API 是高度实验性的——我不保证此插件将在 mypy 的未来版本中继续工作而无需修改。

    【讨论】:

      猜你喜欢
      • 2017-01-20
      • 2022-10-13
      • 1970-01-01
      • 1970-01-01
      • 2012-02-23
      • 1970-01-01
      • 2020-03-20
      • 2020-08-01
      • 1970-01-01
      相关资源
      最近更新 更多