目录
- typing
- 准备工作
- typing 实践
- Tuple、List、Dict
- `Tuple` - 用于定义元组类型的类型注解
- `Dict` - 用于定义字典类型的类型注解
- `List` - 用于定义列表类型的类型注解
- Union
- Optional
- 小结
typing
在 Python 中,typing
模块提供了一些辅助工具来帮助开发者编写类型注解,这是 Python 3.5 新引入的一项功能,允许开发者为变量、函数的参数和返回值指定预期的类型。
如此,不仅有助于提高代码的可读性,还可以在某些情况下帮助识别潜在的编程错误。
本博文中,我们将首先通过案例 “见一见” 这些常用的功能和类,最后通过表格形式做总结。
准备工作
运行代码时,即使把 str
类型值赋给类型注解为 int
类型时,Python 解释器也不会因为类型不匹配而抛出错误,因为在运行时是动态的。
typing
的用法,是搭配静态类型检查工具(如 mypy
),在代码分析时进行静态检查类型注解。发现实际值与注解类型不匹配的错误并报告。
因此,我们需要下载安装 typing
库与 mypy
库;
pip install typing
pip install mypy
typing 实践
首先我们从
- 元组(Tuple)
- 列表(List)
- 字典(Dict)
这三个类开始;
Tuple、List、Dict
Tuple
- 用于定义元组类型的类型注解
e . g . 1 e.g.1 e.g.1 类型不匹配;
from typing import Tuple
my_tup: Tuple[int] = ("hello")
明显,我们将字符串赋给了类型注解为整型的元组,此时我们使用静态检查工具 mypy
检查:
# Terminal 中执行
mypy .\main.py
报错:
e . g . 2 e.g.2 e.g.2 数量不匹配;
from typing import Tuple
my_tup: Tuple[int] = (1, 2)
我们标记了一个整型的类型注解,但是元组中却有两个整数,此时我们静态检查工具 mypy
检查:
# Terminal 中执行
mypy .\main.py
报错:
e . g . 3 e.g.3 e.g.3 类型、数量皆正确;
from typing import Tuple
my_tup: Tuple[int, int] = (1, 2)
类型、数量皆正确,静态检查工具检查:
mypy .\main.py
结果:
Dict
- 用于定义字典类型的类型注解
from typing import Dict
my_dict_1: Dict[str, int] = {"one": "1", "two": 2}
my_dict_2: Dict[str, int] = {"one": 1, "two": 2}
my_dict_1
错误,my_dict_2
正确:
List
- 用于定义列表类型的类型注解
from typing import List, Any
my_list_1: List[int] = [1, 2, 3, 4]
my_list_2: List[Any] = [1, "two", 3.0]
my_list_1
定义一个包含整数的列表
my_list_2
定义一个泛型列表,可以是任意类型的元素
皆正确:
Union
在类型注解模块 typing
中,支持使用 Union
表示类型之间的联合,变量可以是多种类型中的任意一种。
from typing import Union
def add_numbers(a: Union[int, float], b: Union[int, float]) -> Union[int, float]:
return a + b
# 正确的调用
result_int = add_numbers(1, 2) # 类型为 int
result_float = add_numbers(1.5, 2.5) # 类型为 float
# 错误的调用
result_mixed = add_numbers(1, "hello")
在上面的例子中,add_numbers
函数接受两个参数,这两个参数可以是 int
或 float
类型。函数返回值也可以是 int
或float
类型。
mypy .\main.py
在 Python 3.5 及以后的版本中,类型检查器会允许 int
和 float
之间的混合运算,因为 int
和 float
是相互可转换的类型(在数值上, int
会被转换为 float
进行计算)。但是,如果你需要类型注解来明确地指出不接受混合类型,你可以使用 Union
来明确指出允许的类型。
在 Python 3.5 之前的版本中,上述代码会报错,因为之前的类型检查器不支持混合类型的操作。如果你使用的是早期版本的 Python,需要确保不要混合使用 int
和 float
类型的参数。
Optional
Optional
表示一个值可以是某种类型,或者是 None
。
换句话说,Optional[X]
等价于 Union[X, None]
,表示变量可以是类型 X
或者是 None
。
from typing import Optional
# 函数 greet 中接受一个参数 name,参数可以是 str 类型或者 None
def greet(name: Optional[str] = None) -> str:
if name is None:
return "Hello, there!"
return f"Hello, {name}!"
# 正确的调用
print(greet("Alice")) # 返回 "Hello, Alice!"
print(greet()) # 返回 "Hello, there!"
# 错误的调用
print(greet(123))
在这个例子中,greet
函数接受一个参数 name
,这个参数可以是 str
类型或者是 None
。函数的返回值也是一个 str
,但在没有提供 name
参数时,它会返回一个通用的问候语。
小结
在使用类型注解时,Python 解释器并不会强制检查这些类型,这意味着即使你指定了类型,Python 也不会在运行时检查这些类型是否匹配。然而,如 mypy
的静态类型检查工具可以利用这些注解来提供更好的代码检查和提示。
所以,类型注解只是 Python 的一种语法糖,它不会影响代码的执行,主要是为了提高代码的可读性和易维护性,同时可以被静态类型检查工具使用来减少bug。
2024.2.22