键入提示:何时注释

问题描述 投票:0回答:3

我越来越多地使用类型提示和 mypy。然而,我对何时应该显式注释声明以及何时可以由 mypy 自动确定类型有一些疑问。

例如:

def assign_volume(self, volume: float) -> None:
    self._volume = volume * 1000

我应该写吗

self._volume: float = volume *1000

在这种情况下?

现在如果我有以下功能:

def return_volume(self) -> float:
        return self._volume

以及我的代码中的某个地方:

my_volume = return_volume()

我应该写:

my_volume: float = return_volume()
python python-typing mypy
3个回答
16
投票

Mypy(以及一般的 PEP 484)的设计使得在最理想的情况下,您只需要向代码的“边界”或“接口”添加类型注释。

例如,您基本上必须在以下位置添加注释/类型元数据:

  1. 函数和方法的参数和返回类型。
  2. 任何对象字段(假设仅通过查看构造函数无法推断出字段的类型)
  3. 当你继承一个类时。例如,如果您特别想将 ints 的 dict 子类化为 strs,则应该执行
    class MyClass(Dict[int, str]): ...
    ,而不是
    class MyClass(dict): ...

这些都是代码“边界”的示例。参数/返回类型上的类型提示让函数的调用者确保他们正确调用它,字段上的类型提示让调用者知道他们正在正确使用对象,等等...

然后,

Mypy(以及其他 PEP 484 兼容工具)将使用该信息并尝试推断其他所有内容的类型。这种行为旨在大致模仿人类阅读代码的方式:例如,一旦您知道传入的类型,通常就很容易理解代码的其余部分的作用。

毕竟,Python 是一门从一开始就被设计为可读性的语言!我们不需要到处散布类型提示来增强我们对代码功能的理解。

当然,mypy(和其他符合 PEP 484 的工具)并不完美,有时它们可能无法正确推断某些局部变量的类型。在这种情况下,您可能需要添加类型提示来帮助 mypy 进行操作。 Ethan 的回答 很好地概述了一些需要注意的常见情况。 (有趣的是,这些案例也往往是“人类”读者可能难以理解您的代码的示例!) 因此,将所有内容放在一起,一般建议是:

向代码的所有“边界”添加类型提示,例如函数参数和返回类型。
  1. 默认
  2. 注释变量。如果 mypy 无法推断某个变量应该是什么类型,请添加注释来帮助它。 如果您发现自己需要注释大量变量才能使 mypy 满意,请考虑重构您的代码。如果 mypy 很容易混淆,那么人类读者也可能很容易混淆。
因此,回到您的示例,在任何一种情况下您都
不会

添加类型提示。人类读者和 mypy 都可以告诉你的 _volume 字段必须是浮点数:很明显,情况一定是这样,因为参数是浮点数,并且将浮点数乘以 int 总是会产生另一个浮点数。


同样,您也

不会

向您的my_volume变量添加注释。由于

return_volume()
具有类型提示,因此很容易看到它返回的类型并了解
my_volume
是 float 类型。 (如果你犯了一个错误,无意中认为它不是浮点数,那么 mypy 会为你捕获它。)
    


10
投票

Mypy 将初始赋值视为变量的定义。如果没有显式指定变量的类型,mypy 会根据值表达式的静态类型推断类型

一般的经验法则是“注释其类型在初始赋值时不可推断的变量”。

以下是一些示例:

    空容器。如果我将
  • a

    定义为

    a = []
    ,mypy 将不知道列表中哪些类型是有效的
    a
    
    

  • Optional

    类型。通常,如果我定义

    Optional
    类型,我会将变量分配给
    None
    。例如,如果我这样做
    a = None
    ,mypy会推断
    a
    具有类型
    NoneType
    ,如果稍后你想将
    a
    分配给
    5
    ,你需要注释它:
    a: Optional[int] = None
    
    

  • 复杂的嵌套容器。例如,如果您有一个包含列表值和字符串值的字典,mypy 可能会推断出
  • Dict[str, Any]

    。您可能需要对其进行注释才能更准确。

    
    

  • 当然还有更多的案例。

在您的示例中,mypy 可以推断表达式的类型。

[1]

https://mypy.readthedocs.io/en/latest/type_inference_and_annotations.html


3
投票

© www.soinside.com 2019 - 2024. All rights reserved.