mypy 在评估算术计算的类型时未考虑先前执行的类型检查

Posted

技术标签:

【中文标题】mypy 在评估算术计算的类型时未考虑先前执行的类型检查【英文标题】:mypy not taking previously performed typecheck into account when evaluating types for arithmetic computation 【发布时间】:2022-01-03 17:06:40 【问题描述】:

我有一个如下所示的 python 类:

from typing import Optional, Union, Dict
import numpy as np

class TestClass():

    def __init__(self, a: Optional[float] = None, b: Optional[float] = None):
        self.a = 1 if a is None else a
        self.b = b

    @property
    def input_values(self) -> Dict[str, Union[float, None]]:
        return 'a': self.a, 'b': self.b

    @property
    def test_property(self) -> float:
        if None in self.input_values.values():
            raise KeyError('missing values')

        return self.a+self.b

用 mypy 评估它会返回错误语句

error: Unsupported operand types for + ("float" and "None")
note: Right operand is of type "Optional[float]"

但我要确保在控制流的这一点上这两个值都不能为 None。 mypy 是否可以通过不同的方式来执行这些类型检查?

【问题讨论】:

你必须看到mypy没有做运行时分析。所以它不会从测试if None in self.input_values.values() 中学到任何东西,因为它需要实际执行方法input_values。对于 mypy,在您的 return 语句中,self.b 的类型为 Optional[float](因为它在 __init__ 方法中进行了初始化)。就是这样。 @qouify 但如果我将稍后用于算术的值的输入类型设置为 Optional[float] mypy 会引发错误。我还能保留此功能并继续使用 mypy 吗? 如果您真的需要 b 成为 Optional[float] 而不是像您对 a 所做的那样强制它成为 float,您可以随时使用 cast确保b 肯定不能包含None,就像这样:typing.cast(float, self.b)。 mypy 可以在其类型检查中利用此信息。 (顺便说一句,你或许应该删除你以前的帖子,这似乎是这篇文章的草稿。) 你有什么理由去构建一个辅助dict 进行检查吗?一个简单的if self.b is None: 就足够了。 【参考方案1】:

mypy 中类型的缩小非常有限,允许的方法之一是 assert,这在 mypy 中有效:

def test_property(self) -> float:
    if None in self.input_values.values():
        raise KeyError('missing values')
    assert isinstance(self.a, float) and isinstance(self.b, float)
    return self.a + self.b

【讨论】:

以上是关于mypy 在评估算术计算的类型时未考虑先前执行的类型检查的主要内容,如果未能解决你的问题,请参考以下文章

评估 numpy.radians 和浮点/数组输入元素的类型提示

将值列表映射到浮点数时出现mypy错误

mypy 错误 - 尽管使用了“Union”,但类型不兼容

类装饰器上的 Mypy 注释

使用 mypy 的 NumPy ndarray 的特定类型注释

使用元组列表重塑数组时出现 mypy 错误