[Python] typing 模块 : Python 3 内置模块 [Python 3.5 - ]
概述: typing 模块 (Python 内置模块)
简介
- Python 的
typing模块自Python 3.5版本引入,为静态类型注解提供了支持。
这个模块主要用于增强代码的可读性和维护性,尽管 Python 是一种动态类型语言,类型注解使得开发者能够更清晰地了解函数和变量的预期类型。
类型别名和新类型
- 类型别名,是使用 type 语句定义的,它创建一个 TypeAliasType 的实例。例如,Vector 和 list[float] 将被静态类型检查器等同处理。类型别名适用于简化复杂的类型签名。NewType 助手则用于创建与原类型不同的新类型,这对于捕捉逻辑错误很有用。
可调用对象的标注
- 函数或其他可调用对象可以使用
collections.abc.Callable或typing.Callable来标注。
例如,Callable[[int], str] 表示一个接受 int 类型的单个参数并返回 str 的函数。
泛型(Generic)
- 泛型,允许通过使用类型形参语法来实现参数化,从而为容器元素添加预期的类型。例如,Sequence[Employee] 表示序列中的所有元素都必须是 Employee 实例。
标注元组
- 元组在 Python 的类型系统中是特殊情况,可以接受任意数量的类型参数。例如,
tuple[int, str]表示一个长度为 2 的元组,第一个元素是 int,第二个是 str。
类对象的类型
- 用 C 注解的变量可以接受类型 C 的值。而用类型 type[C] 注解的变量则可以接受 C 的类对象。
用户定义的泛型类型
用户定义的类可以定义为泛型类。例如,LoggedVar[T] 表示类 LoggedVar 是围绕单个类型变量 T 实现参数化的。
Any 类型
- Any 是一种特殊的类型,表示没有约束的类型。所有类型都与 Any 兼容,反之亦然。
名义子类型 vs 结构子类型
- Python 静态类型系统最初被定义为使用名义子类型,这意味着类 A 必须是 B 的子类才能使用。PEP 544 允许结构子类型,也称为静态鸭子类型。
模块内容
typing 模块定义了一系列的类、函数和装饰器,如 Any、Union、Tuple、Callable、TypeVar 和 Generic 等。
特殊类型原语
- typing 模块中的特殊类型原语,如 Any、Union、Optional、Literal、Final 和 TypeAlias,用于在注解中表示类型。
特殊形式
- typing 模块中的特殊形式,如 Union、Optional、Concatenate 和 Literal,支持下标用法,并具有唯一的语法。
构造泛型类型与类型别名
typing.Generic用于泛型类型的抽象基类,而 typing.TypeVar 和 typing.ParamSpec 用于构造类型变量和形参专属变量。
其他特殊指令
- typing 模块中的其他特殊指令,如 NamedTuple、NewType、Protocol、runtime_checkable 和 TypedDict,用于创建和声明类型。
类型检查工具
- 可以使用 mypy 等静态类型检查工具进行类型检查,以确保代码符合类型注解。
注意事项
- 静态类型检查工具辅助,不会影响 Python 的动态特性,可以选择性地使用类型注解。类型注解应该让代码更易于理解,但不应使代码变得过于复杂。
Union
简介
- 作用
在 Python 的类型提示(Type Hints)中,
Union是一个非常重要的工具,用于指定一个变量或函数参数可以接受多种类型中的任意一种。
其来自typing模块。
Union 的主要作用是允许一个变量或参数具有多种可能的类型,而不是单一的类型。这在实际开发中非常有用,因为某些函数可能需要处理多种类型的输入,而 Union 可以明确地表达这种需求。
- 使用方法
Union的语法是Union[Type1, Type2, ...],其中Type1、Type2等是可能的类型。
从 Python 3.10 开始,Union 也可以通过|操作符来表示,这种方式更简洁。
- 简答示例
from typing import Union
# 使用 Union 指定变量可以是 int 或 str
def add_or_concatenate(a: Union[int, str], b: Union[int, str]) -> Union[int, str]:
if isinstance(a, int) and isinstance(b, int):
return a + b
elif isinstance(a, str) and isinstance(b, str):
return a + b
else:
raise TypeError("Both arguments must be of the same type: int or str")
# 使用 | 操作符(Python 3.10+)
def add_or_concatenate(a: int | str, b: int | str) -> int | str:
if isinstance(a, int) and isinstance(b, int):
return a + b
elif isinstance(a, str) and isinstance(b, str):
return a + b
else:
raise TypeError("Both arguments must be of the same type: int or str")
- 优点
- 类型安全:通过明确指定变量或参数可以接受的类型,可以减少运行时错误。
- 代码可读性:让代码的意图更加清晰,其他开发者更容易理解函数的输入和输出。
- 静态类型检查:工具(如 mypy)可以利用这些类型提示进行静态类型检查,提前发现潜在的类型错误。
- 注意事项
- 尽量避免过度使用:虽然 Union 提供了灵活性,但过多使用可能会使代码变得复杂。如果可能,尽量将函数或变量的类型限制为单一类型。
- 兼容性:在 Python 3.10 之前,必须使用 Union,而在 Python 3.10 及以上版本中,可以使用
|操作符,但需要确保代码的兼容性。
使用场景: 当函数需要接受多种类型的入参/出参或变量时,Union 可明确地表达这一点
- 使用场景
场景1 - 函数参数:当函数需要接受多种类型的参数时,使用 Union 可以明确地表达这一点。
def process_data(data: Union[int, float, str]) -> None:
if isinstance(data, int):
print(f"Processing integer: {data}")
elif isinstance(data, float):
print(f"Processing float: {data}")
elif isinstance(data, str):
print(f"Processing string: {data}")
场景2 - 返回值:当函数的返回值可能有多种类型时,也可以使用 Union。
def get_value(condition: bool) -> Union[int, str]:
if condition:
return 42
else:
return "Hello"
场景3 - 变量类型:在定义变量时,也可以使用 Union 来指定变量可以是多种类型。
from typing import Union
value: Union[int, str] = 10
value = "Hello" # 也可以是字符串
BinaryIO
使用场景: typing.io.BinaryIO(): 打开和读取二进制文件
- 在
Python中,typing.io.BinaryIO()是一个类型提示函数,它表示二进制输入/输出流。
它可以用于函数或方法参数类型注释,以指示预期的输入或输出类型。
这对于静态类型检查和代码文档生成非常有用。
- 要打开和读取二进制文件,我们可以使用内置的
open()函数,并指定打开模式为二进制模式('rb')。
from typing import BinaryIO
def read_binary_file(fileBinBytes: BinaryIO, byteSize: int) -> bytes:
data = fileBinBytes.read(byteSize)
return data
# 打开二进制文件
with open('example.blf', 'rb') as fileBinBytes:
# 读取文件内容
binary_data = read_binary_file(fileBinBytes, 10)
# 处理二进制数据
print(binary_data)
byte_count = len(binary_data)
print(f"字节数为: {byte_count} bytes")
out
b'LOGG\x90\x00\x00\x00\x947'
分析:
b'LOGG':4 个字节(每个字符占用 1 个字节)
\x90:1 个字节(十六进制表示的字节)
\x00\x00\x00:3 个字节(3 个零字节)
\x94:1 个字节
b'7':1 个字节
案例:读写数据到文件
from typing import BinaryIO
def read_file(file: BinaryIO) -> None:
# 读取文件内容
data = file.read()
# 打印文件内容
print(data)
def write_file(file: BinaryIO, data: bytes) -> None:
# 写入数据到文件
file.write(data)
# 打开二进制文件进行读取
with open('example.bin', 'rb') as file:
read_file(file)
# 打开二进制文件进行写入
with open('example.bin', 'wb') as file:
write_file(file, b'Hello, World!')
X 参考文献
本文作者:
千千寰宇
本文链接: https://www.cnblogs.com/johnnyzen
关于博文:评论和私信会在第一时间回复,或直接私信我。
版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!
日常交流:大数据与软件开发-QQ交流群: 774386015 【入群二维码】参见左下角。您的支持、鼓励是博主技术写作的重要动力!
本文链接: https://www.cnblogs.com/johnnyzen
关于博文:评论和私信会在第一时间回复,或直接私信我。
版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!
日常交流:大数据与软件开发-QQ交流群: 774386015 【入群二维码】参见左下角。您的支持、鼓励是博主技术写作的重要动力!

浙公网安备 33010602011771号