Python 中的 typing 使用

Python 中的 typing 使用

主要是概括 pep-0484 的对 python 中类型检查的使用。pep-3107 中开始提出引入元信息对 python 中的函数(变量)进行注释。类型提示的主要目的是让静态分析工具和类型检查器能够提高代码质量和在运行时之前发现错误。类型提示是可选的,对代码的运行时行为没有影响。注释本身可以在运行时通过__annotations__属性访问获得,但是不会在运行时(runtime)进行类型检查

# 一个简单的注释例子。
def greeting(name: str) -> str:
	return 'Hello' + name

动机

提高代码的可读性、可维护性和更健壮的代码,同时也可以让 IDE 正确地对代码进行显示补全(直观点的就是 VS Code 中代码的颜色)

语法

类型别名

使用 TypeVar 自定义类型,或者现有类型进行重命名或组合命名,具体见下方例子:

# 简单赋值重命名
Url = str
def retry(url: Url, retry_count: int) -> None: ...

# 复杂类型,并进行自命名
from typing import TypeVar, Iterable, Tuple

T = TypeVar('T', int, float, complex)
# 这里也可以不重命名为Vector,可以直接使用Iterable[Tuple[T, T]]
Vector = Iterable[Tuple[T, T]]

def inproduct(v: Vector[T]) -> T:
    return sum(x*y for x, y in v)
def dilate(v: Vector[T], scale: T) -> Vector[T]:
    return ((x * scale, y * scale) for x, y in v)
vec = []  # type: Vector[float]

函数 (callable)

在使用回调函数时为了方便代码 debug 和阅读,可以使用 Callable[[Arg1Type, Arg2Type], ReturnType] 来进行注释。下面给出具体的例子:

from typing import Callable

def feeder(get_next_item: Callable[[], str]) -> None:
    # Body

def async_query(on_success: Callable[[int], None],
                on_error: Callable[[int, Exception], None]) -> None:
    # Body
# 也支持用ellipsis来省略可调用的输入参数类型
def partial(func: Callable[..., str], *args) -> Callable[..., str]: ...

泛型 (generic)

容器中对象的类型信息不能以一种通用方式 (generic way)推理出来。因此通过使用 typing 中的 TypeVar 来定义泛型(Generics),进而表明容器中对象的类型。

from typing import Sequence, TypeVar
T = TypeVar('T')
def first(l: Sequence[T]) -> T:
	return l[0]

在泛型的使用中也有以下几点需要注意:

T = TypeVar ('T')

在不指定类型的情况下,此时 T 会自动链接输入的类型

from typing import TypeVar, Text
def identity_int(arg: int) -> int: return arg
def identity_str (arg: str) -> str: return arg
# 上述的代码可以转换为
T = TypeVar("T")
def identity (arg: T) -> T: return arg
# 这里还要注意甄别下 | 类型和 T 的区别
def identity (arg: int | str) -> int | str: return value
# 同时还要注意在 TypeVar 中传入多个类型时,不能混合。以下面的例子,一个输入是另一个输入则必须也是Text
AnyStr = TypeVar ('AnyStr', Text, bytes)
def concat (x: AnyStr, y: AnyStr) -> AnyStr: return x + y
其他泛型注释

  • List
  • Dict
  • set
    需要注意的是以上应该都可以通过抽象抽象基类来注释,使用抽象基类时,可以标注出参数类型
  • Iterable
  • Sequence
  • Mapping

其他常用的归纳

typing 中其他常用的类型注释

类型提示遵循一些通用的规则和约定 :