Python 类型提示
简介
Python 的类型提示(Type Hints)是在 Python 3.5 中正式引入的,作为 PEP 484 – Type Hints 的一部分。它是一种在代码中显式声明变量、参数、返回值等的类型信息的方式。它对代码运行没有实际影响,只是作为一种可选的静态类型标注,意在为开发者提供变量、参数和返回值的类型信息,方便代码阅读。
可以把类型提示当作一种注释,就是告诉开发者这个变量“应该”是提示的类型,但是 python 编译器本身不做类型检查,即便代码运行时这个变量不是标注的类型,也不会有任何提示。
普通变量的类型提示
在创建变量时可以进行类型提示
1 | x: int = 1 |
还可以对一些自定义的数据类型进行提示
1 | import numpy |
函数参数和返回值类型
在函数定义中,可以为参数和返回值添加类型提示:
1 | def add(x: int, y: int) -> int: |
-> int
表示函数的返回值应该是整数。
这里使用 “应该” 是表示 Python 编译器并不强制用户在调用这个 add 函数时传入非 int 类型的数据,即 Python 编译器不做类型检查,这个类型提示的功能只是作为 “提示”。如果需要进行类型检查还需要额外添加类型检查的语句,例如:
1 | def add(x: int, y: int) -> int: |
list / tuple
直接提示 list / tuple
如果只想说明变量的类型为 list / tuple,不需要额外说明 list / tuple 中元素的类型,可以直接使用 list / tuple 来进行类型提示
1 | def func1(data: list) -> None: |
提示元素的类型
如果还需要说明 list / tuple 中元素的类型,例如 list[int, ...]
、tuple[str, int]
这种类型的提示,则要分两种情况:
python 3.8 及以下版本中需要从 typing 中引入 List 和 Tuple,才能使用类似 List[int, ...]
这种类型提示
1 | from typing import List, Tuple |
python 3.9 及以上版本,则可以直接使用 list[int, ...]
进行提示
1 | # python 3.9+ |
如果在 3.8 及以下版本中使用 list[int, ...]
或者 tuple[int, str]
这种类型提示则会报如下错误
1 | TypeError: 'type' object is not subscriptable |
提示元素的个数
List 与 Tuple 本身并不限制它的元素的个数和元素的数据类型,它的元素类型可以是任意的,长度也可以是任意的。而 List[int, ...]
和 Tuple[str, int]
这种类型提示除了提示其中元素的类型还额外提示了元素的个数。
List[int]
表示这是一个仅包含单个 int 类型数据的 List,即它的长度为 1;List[int, ...]
表示这是一个仅包含 int 类型数据的 List,它的长度不确定,但是元素类型必须是 int 类型;List[int, str]
表示这个一个仅包含两个元素的长度为 2 的 List,并且它的第一个元素为 int 类型,第二个元素为 str 类型。
list vs tuple
注意,tuple 与 list 的主要区别在于用户不能修改 tuple 中的元素,当你尝试使用赋值语句修改 tuple 中元素的值时,会如下报错
1 | TypeError: 'tuple' object does not support item assignment |
所以 tuple 可以看作是一种 const 的 list。
dict
dict 类型提示的用法同样在 python 3.8 和 python 3.9+ 中有所区别,下面以 python 3.9+ 进行说明。
提示 data 是一个 key 为 str 类型,value 为 int 类型的字典
1 | data: dict[int, str] = {1: "Alice", 2: "Bob"} |
还可以使用带有嵌套的写法
1 | data: dict[str, dict[str, int]] = { |
Union
使用 Union 可以提示多种数据类型。例如
1 | from typing import Union |
表示 data 是一个 list,并且其中元素的类型是 int 或者 str。
Any
使用 Any 表示数据类型不做限制。例如
1 | from typing import Any |
表示 data 是一个 dict,而其中的 key 需要时 str 类型,而 value 可以时任意类型。
Optional
Optional 作为一种类型标注,用于表示变量可以是某种类型,也可以是 None。例如 Optional[int]
表示被提示变量的数据类型可以是 int 或者是 None。Optional[int]
与 Union[int, None]
这两者是等价的, Optional 本质上是 Union 类型的一种快捷写法。
1 | from typing import Optional, Union |
Union & |
在 Python 类型提示中,如果希望提示一个变量可以是多种可选类型,例如 int
或 float
类型,可以使用 Union
(Python 3.9 及以下版本)或 |
(Python 3.10 及以上版本)来进行类型注解。
Python 3.10 及以上版本
可以使用 |
运算符来指定多个可选的类型:
1 | def func(value: int | float) -> None: |
Python 3.9 及以下版本
在 Python 3.9 及以下版本中,使用 Union
来指定多种类型:
1 | from typing import Union |
Literal
Literal 是一种轻量级的值约束,主要用于类型提示,适合限制参数或变量的取值范围,同样它仅仅作为提示,而不进行类型检查,是个君子协定。
1 | from typing import Literal |
Literal 可以处理简单的情况,在面临复杂的值约束时,建议使用 Python 的枚举类型
1 | from enum import Enum |