# ♢ typing
:Python 的标准库,定义了一些类型,常用于类型注释。
# 类型
- Python 变量本身是无类型的,但可以添加类型注释,供 IDE 等工具进行静态类型检查。
- 类型:可以是 str、list 等内置类,或用户定义的类,或泛型类。
- 类型别名(Type Alias):指将一个类型赋值给一个变量。
>>> T = int >>> x : T = 1
# 常见类型
Any # 匹配所有类型
List
Tuple # 元组。比如 Tuple[int, str] 表示取值为一个元组,包含两个指定类型的值。
Sequence # 序列
Set
Dict
Iterable # 可迭代对象
# Callable
:表示可调用的对象。
- 例:
>>> from typing import Callable >>> x : Callable # 表示变量 x 是一个可调用对象 >>> x : Callable[[int, int], str] # 表示变量 x 可调用,且形参列表为 [int, int] 类型,返回值为 str 类型
# Optional
:表示取值是可选的。可以不赋值,即相当于赋值 None 。
- 例:
from typing import Optional def foo(arg: Optional[int] = None): pass
# Union
:表示属于多种类型之一,称为联合类型。
- 定义 Union 类型时,
- 如果只包含一个类型,则只返回该类型。
>>> Union[int] <class 'int'>
- 如果包含了重复的类型,则会去除重复:
>>> Union[int, int] <class 'int'>
- 如果嵌套了 Union 类型,则自动合并为一层 Union 。
>>> Union[Union[int, str], float] typing.Union[int, str, float]
- 如果只包含一个类型,则只返回该类型。
- 比较两个 Union 类型时,不考虑参数的顺序。
>>> Union[int, str] == Union[str, int] True >>> Union[int, str, int] == Union[str, int] True
# Type
:type 的别名。
- 例:
>>> from typing import Type >>> x : Type
# TypeVar
:用于定义类型变量,表示一种类型。
- 例:
>>> from typing import TypeVar >>> A = TypeVar('A') # 定义一个类型变量 A ,可以赋值任意类型 >>> A ~A >>> B = TypeVar('B', int, str) # 定义一个类型变量 B ,只能赋值指定的类型 >>> x : B = 1
- TypeVar 变量可用作泛型的参数:
>>> from typing import Sequence, TypeVar >>> T = TypeVar('T') >>> x : Sequence # Sequence 是一个已定义的泛型 >>> x : Sequence[T] >>> x : Sequence[T, T] # Sequence 只支持声明一个参数 TypeError: Too many arguments for typing.Sequence; actual 2, expected 1
# Generic
:用作泛型类的抽象基类。
- 泛型类:表示一个任意类型的类,只声明了形参的类型、数量。
- Generic 类的定义:
class Generic: def __class_getitem__(cls, params): ... def __init_subclass__(cls, *args, **kwargs): ...
- 例:定义泛型类
>>> from typing import TypeVar, Generic >>> A = TypeVar('A') >>> B = TypeVar('B') >>> class Test(Generic): # 继承 Generic 时,必须声明参数 ... pass ... TypeError: Cannot inherit from plain Generic >>> class Test(Generic[A]): ... pass ... >>> class Test(Generic[A, A]): # 如果声明多个参数,则必须互不相同 ... pass ... TypeError: Parameters to Generic[...] must all be unique >>> class Test(Generic[A, B]): ... def __init__(self, x:A=None, y:B=None): ... pass ... >>> Test() # 创建泛型类的示例时,可以不声明参数,像普通类一样使用 <__main__.Test object at 0x7f21e0369ff0> >>> Test[A]() # 如果声明了参数,则会检查参数数量是否一致,否则抛出异常。但不会强制类型检查 File "/usr/local/lib/python3.10/typing.py", line 1316, in __class_getitem__ _check_generic(cls, params, len(cls.__parameters__)) TypeError: Too few arguments for <class '__main__.Test'>; actual 1, expected 2 >>> Test[int, int]() <__main__.Test object at 0x7f21e0368910> >>> Test[int, str](1, 2) # 不会强制类型检查 <__main__.Test object at 0x7f347beb5270>