Pycharm 静态类型检查器失败

Posted

技术标签:

【中文标题】Pycharm 静态类型检查器失败【英文标题】:Pycharm static type checker fails 【发布时间】:2021-02-28 04:33:57 【问题描述】:

也许有人可以在这里帮助我。 我一直在为这个pycharm集成的静态类型检查器苦苦挣扎。

一些规格:

Python 3.7.7 Windows 10 专业版 x64

我尝试了以下 PyCharm 版本。

专业2020.1.3 社区 2020.2.3

我试图说明问题。您可以将其复制并粘贴到您的 PyCharm 中以验证问题。

class SpecificCLS:
    pass


class CLS:
    def __init__(self):
        self.integer: int = 0
        self.specific_cls: SpecificCLS = SpecificCLS()

    def set_im_int(self, value: int):
        self.integer = value

    def get_im_int(self) -> int:
        return self.integer

    def get_specific_cls(self) -> SpecificCLS:
        return self.specific_cls

    def set_specific_cls(self, value: SpecificCLS):
        self.specific_cls = value


cls = CLS()

# Example for assigning a class into an integer
cls.integer = SpecificCLS()  # PyCharm does NOT show any error/warning that a class is assigned into an variable that is declared as an "int"
cls.set_im_int(SpecificCLS())  # PyCharm recognise an error (underlined red): Expected type 'int', got 'SpecificCLS' instead

# Example for assigning an integer into a class
cls.specific_cls = 1  # PyCharm does NOT show any error/warning that a class is assigned into an variable that is declared as an "int"
cls.set_specific_cls(1)  # PyCharm recognise an error (underlined red): Expected type 'SpecificCLS', got 'int' instead

PyCharm Screenshot

如果您查看这一行,您会注意到没有显示错误。

cls.integer = SpecificCLS()  # PyCharm does NOT show any error/warning that a class is assigned into an variable that is declared as an "int"

如果我们使用 setter 方法来赋值,pycharm 会正确识别错误的赋值。

cls.set_im_int(SpecificCLS())  # PyCharm recognise an error (underlined red): Expected type 'int', got 'SpecificCLS' instead

那么谁能告诉我为什么 setter 的类型检查工作得很好,但其他分配却不行?

到目前为止,我一直使用 getter/setter 来验证我是否会为彼此分配正确的类型。因此我用'__'标记了私有字段,这样没有人可以直接更改状态。 由于我已经从 python 3.5.x 更新到 3.7.x,我认为我可以删除这个样板代码。我想要那种静态类型检查功能,但我不想强迫我一直使用 getter/setter。

感谢您的帮助。

最好的问候

2020 年 11 月 18 日更新:12:00 很抱歉这个误导性的例子。我试图编辑剪辑并希望问题现在很清楚。我还尝试更详细地解释我在 pycharm 的执行/性能中看到的问题。我还添加了更新的屏幕截图。

【问题讨论】:

这能回答你的问题吗? Mypy doesn't throw an error when mixing booleans with integers 【参考方案1】:

Pycharm 和 mypy 都是正确的,因为 bool 派生自 int,并且通过表明您想要一个 int,您接受任何类型派生自 int 的变量。

您可以通过 issubclass(bool, int) 验证 bool 是从 int 派生的

【讨论】:

感谢您的快速回复。我根据您的说明更新了我的问题。【参考方案2】:

在@Sylvaus 的帮助下,我找出了问题所在并找到了解决方案。

PyCharm 无法识别出违反 PEP-526 的行为,但 mypy 正确识别! 通过

安装Mypy插件

文件 -> 设置 -> 插件

如果你运行 mypy,它会告诉你现在有错误。但是需要一些时间才能触发 pycharms 分析器并显示 mypy 的结果。

我将尝试将分析器绑定到代码格式快捷方式。如果我能做到,我会更新这篇文章。

编辑: 感谢user2235698,这是来自jetbrains https://youtrack.jetbrains.com/issue/PY-36889的issue

【讨论】:

这不是真的,PyCharm 自 2016 年以来 (youtrack.jetbrains.com/issue/PY-20744) 就支持 PEP 526,请在类级别上注释您的属性,所有预期的警告都会引发。 @user2235698 为什么它无法识别上例中的违规行为?为什么我应该使用类变量而不是实例变量? 不会是类变量,例如:class MyClass: integer: int,会是类级别的注解 嗯。我试过了,但 PyCharm 类型检查器仍然没有警告。 Mypy 确实向我显示了警告。 对不起,你是对的:youtrack.jetbrains.com/issue/PY-36889

以上是关于Pycharm 静态类型检查器失败的主要内容,如果未能解决你的问题,请参考以下文章

如何在静态类型检查时运行代码 [重复]

Python 装饰器使用静态方法。但使用 2 个静态方法失败。为啥?

pycharm 对代码做静态检查

Simple JavaJava中静态类型检查是如何进行的

函数包装器静态检查 HTTP 响应的参数

Java中静态类型检查是如何进行的