微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

为什么 Mypy 在 __init__ 中分配类主体中已提示类型的属性时没有给出输入错误? MyPy:Function signatures and dynamic vs static typing

如何解决为什么 Mypy 在 __init__ 中分配类主体中已提示类型的属性时没有给出输入错误? MyPy:Function signatures and dynamic vs static typing

这是我拥有的示例 python 文件

class Person:
    name: str
    age: int

    def __init__(self,name,age):
        self.name = name
        self.age = age


p = Person(5,5)

但是当我运行 mypy test.py 时,我得到以下输出

$ mypy test.py                     
Success: no issues found in 1 source file

难道它不应该抱怨它试图将 5 分配给 name 变量并且我已经指出它应该是 str 类型

解决方法

TLDR:注释初始化程序,而不是字段:

class Person:
    def __init__(self,name: str,age: int):
        self.name = name
        self.age = age

p = Person(5,5)  #  Argument 1 to "Person" has incompatible type "int"; expected "str"

有关此样式,请参阅 mypy Class Basics


这里有两个问题:

  • MyPy 不会检查完全未注释的函数/方法:

    MyPy:Function signatures and dynamic vs static typing

    没有类型注解的函数会被mypy认为是动态类型的:

    def greeting(name):
        return 'Hello ' + name
    

    默认情况下,mypy 不会对动态类型函数进行类型检查。这意味着除了少数例外,mypy 不会报告任何常规未注释 Python 的错误。

    如果您想消除此类问题,请使用标志 --disallow-untyped-defs--check-untyped-defs

  • 未注释的参数默认为 Any

    class Person:
        name: str
        age: int
    
        def __init__(self,name,age: int) -> None:
            self.name = name
            reveal_type(name)       # Revealed type is 'Any'
    
            reveal_type(self.name)  # Revealed type is 'builtins.str'
            self.age = age
    

    即使您的 __init__ 被选中,它的参数也会采用并提供始终兼容的 Any 类型。

要直接解决这两个问题,如果两者一致,则注释初始化器参数而不是类槽。如果 __init__ 是自动生成的,则仅注释类槽,例如通过 dataclasses.dataclasstyping.NamedTuple,或者如果推理不够精确,则另外对它们进行注释。

,

使用 reveal_type 为您提供了为什么会发生这种情况的有用提示:

class Person:
    name: str
    age: int

    def __init__(self,age):
        self.name = name
        self.age = age
        reveal_type(self.name)


p = Person(5,5)

输出:

test_mypy1.py:8: note: Revealed type is 'Any'
test_mypy1.py:8: note: 'reveal_type' always outputs 'Any' in unchecked functions

所以原因是默认情况下,Mypy 根本不检查 __init__ 方法的类型错误,因为您没有对其进行类型注释。

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。