typing --- 类型提示支持¶
3.5 新版功能.
源码: Lib/typing.py
注解
Python 运行时不强制执行函数和变量类型注解,但这些注解可用于类型检查器、IDE、静态检查器等第三方工具。
本模块为 PEP 484 、PEP 526 、PEP 544 、PEP 586 、PEP 589 和 PEP 591 中的类型提示提供运行时支持。Any、Union、Tuple、Callable、TypeVar 和 Generic 等类型是最基础的组件。完整说明详见 PEP 484,类型提示简介请参阅 PEP 483。
下面的函数接收与返回的都是字符串,注解方式如下:
def greeting(name: str) -> str:
return 'Hello ' + name
greeting 函数中,参数 name 的类型是 str,返回类型也是 str。子类型也可以当作参数。
类型别名¶
把类型赋给别名,就可以定义类型别名。本例中,Vector 和 list[float] 相同,可互换:
Vector = list[float]
def scale(scalar: float, vector: Vector) -> Vector:
return [scalar * num for num in vector]
# typechecks; a list of floats qualifies as a Vector.
new_vector = scale(2.0, [1.0, -4.2, 5.4])
类型别名适用于简化复杂的类型签名。例如:
from collections.abc import Sequence
ConnectionOptions = dict[str, str]
Address = tuple[str, int]
Server = tuple[Address, ConnectionOptions]
def broadcast_message(message: str, servers: Sequence[Server]) -> None:
...
# The static type checker will treat the previous type signature as
# being exactly equivalent to this one.
def broadcast_message(
message: str,
servers: Sequence[tuple[tuple[str, int], dict[str, str]]]) -> None:
...
注意,None 是一种类型提示特例,已被 type(None) 取代。
NewType¶
NewType() 辅助函数可创建不同的新类型:
from typing import NewType
UserId = NewType('UserId', int)
some_id = UserId(524313)
静态类型检查器把新类型当作原始类型的子类,这种方式适用于捕捉逻辑错误:
def get_user_name(user_id: UserId) -> str:
...
# typechecks
user_a = get_user_name(UserId(42351))
# does not typecheck; an int is not a UserId
user_b = get_user_name(-1)
UserId 类型的变量可执行所有 int 操作,但返回结果都是 int 类型。这种方式允许在预期 int 时传入 UserId,还能防止意外创建无效的 UserId:
# 'output' is of type 'int', not 'UserId'
output = UserId(23413) + UserId(54341)
注意,只有静态类型检查器强制执行这些检查。在运行时,Derived = NewType('Derived', Base) 语句把 Derived 当作函数,该函数直接返回传递给它的任何参数。即,Derived(some_value) 表达式不创建新类,或引入超出调用常规函数的开销。
更确切地说,在运行时,some_value is Derived(some_value) 表达式总为 True。
也就是说,不能创建 Derived 的子类型,因为,在运行时,它是标识函数,不是真正的类型:
from typing import NewType
UserId = NewType('UserId', int)
# Fails at runtime and does not typecheck
class AdminUserId(UserId): pass
但是,可以基于 '派生的' NewType 创建 NewType():
from typing import NewType
UserId = NewType('UserId', int)
ProUserId = NewType('ProUserId', UserId)
同时,ProUserId 的类型检查也可以按预期执行。
详见 PEP 484。
注解
回顾上文,类型别名声明了两种彼此 等价 的类型。 Alias = Original 时,静态类型检查器认为 Alias 与 Original 完全等价。 这种方式适用于简化复杂类型签名。
反之,NewType 声明把一种类型当作另一种类型的 子类型。Derived = NewType('Derived', Original) 时,静态类型检查器把 Derived 当作 Original 的 子类 ,即,Original 类型的值不能用在预期 Derived 类型的位置。这种方式适用于以最小运行时成本防止逻辑错误。
3.5.2 新版功能.
可调对象(Callable)¶
预期特定签名回调函数的框架可以用 Callable[[Arg1Type, Arg2Type], ReturnType] 实现类型提示。
例如:
from collections.abc 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
无需指定调用签名,用省略号字面量替换类型提示里的参数列表: Callable[..., ReturnType],就可以声明可调对象的返回类型。
泛型(Generic)¶
容器中,对象的类型信息不能以泛型方式静态推断,因此,抽象基类扩展支持下标,用于表示容器元素的预期类型。
from collections.abc import Mapping, Sequence
def notify_by_email(employees: Sequence[Employee],
overrides: Mapping[str, str]) -> None: ...
typing 模块中新推出的 TypeVar 工厂函数实现泛型参数化。
from collections.abc import Sequence
from typing import TypeVar
T = TypeVar('T') # Declare type variable
def first(l: Sequence[T]) -> T: # Generic function
return l[0]
用户定义的泛型类型¶
用户定义的类可以定义为泛型类。
from typing import TypeVar, Generic
from logging import Logger
T = TypeVar('T')
class LoggedVar(Generic[T]):
def __init__(self, value: T, name: str, logger: Logger) -> None:
self.name = name
self.logger = logger
self.value = value
def set(self, new: T) -> None:
self.log('Set ' + repr(self.value))
self.value = new
def get(self) -> T:
self.log('Get ' + repr(self.value))
return self.value
def log(self, message: str) -> None:
self.logger.info('%s: %s', self.name, message)
Generic[T] 是定义类 LoggedVar 的基类,该类使用单类型参数 T。在该类体内,T 是有效的类型。
Generic 基类定义了 __class_getitem__() ,因此,LoggedVar[t] 也是有效类型:
from collections.abc import Iterable
def zero_all_vars(vars: Iterable[LoggedVar[int]]) -> None:
for var in vars:
var.set(0)
泛型类型支持多个类型变量,不过,类型变量可能会受到限制:
from typing import TypeVar, Generic
...
T = TypeVar('T')
S = TypeVar('S', int, str)
class StrangePair(Generic[T, S]):
...
Generic 类型变量的参数应各不相同。下列代码就是无效的:
from typing import TypeVar, Generic
...
T = TypeVar('T')
class Pair(Generic[T, T]): # INVALID
...
Generic 支持多重继承:
from collections.abc import Sized
from typing import TypeVar, Generic
T = TypeVar('T')
class LinkedList(Sized, Generic[T]):
...
继承自泛型类时,可以修正某些类型变量:
from collections.abc import Mapping
from typing import TypeVar
T = TypeVar('T')
class MyDict(Mapping[str, T]):
...
比如,本例中 MyDict 调用的单参数,T。
未指定泛型类的类型参数时,每个位置的类型都预设为 Any。下例中,MyIterable 不是泛型,但却隐式继承了 Iterable[Any]:
from collections.abc import Iterable
class MyIterable(Iterable): # Same as Iterable[Any]
还支持用户定义的泛型类型别名。例如:
from collections.abc import Iterable
from typing import TypeVar, Union
S = TypeVar('S')
Response = Union[Iterable[S], int]
# Return type here is same as Union[Iterable[str], int]
def response(query: str) -> Response[str]:
...
T = TypeVar('T', int, float, complex)
Vec = Iterable[tuple[T, T]]
def inproduct(v: Vec[T]) -> T: # Same as Iterable[tuple[T, T]]
return sum(x*y for x, y in v)
在 3.7 版更改: Generic 不再支持自定义元类。
抽象基类可作为用户定义的泛型类的基类,且不会与元类冲突。现已不再支持泛型元类。参数化泛型的输出结果会被缓存,typing 模块的大多数类型都可哈希、可进行等价对比。
Any 类型¶
Any 是一种特殊的类型。静态类型检查器认为所有类型均与 Any 兼容,同样,Any 也与所有类型兼容。
也就是说,可对 Any 类型的值执行任何操作或方法调用,并赋值给任意变量:
from typing import Any
a = None # type: Any
a = [] # OK
a = 2 # OK
s = '' # type: str
s = a # OK
def foo(item: Any) -> int:
# Typechecks; 'item' could be any type,
# and that type might have a 'bar' method
item.bar()
...
注意,Any 类型的值赋给更精确的类型时,不执行类型检查。例如,把 a 赋给 s,在运行时,即便 s 已声明为 str 类型,但接收 int 值时,静态类型检查器也不会报错。
此外,未指定返回值与参数类型的函数,都隐式地默认使用 Any:
def legacy_parser(text):
...
return data
# A static type checker will treat the above
# as having the same signature as:
def legacy_parser(text: Any) -> Any:
...
return data
需要混用动态与静态类型代码时,此操作把 Any 当作 应急出口。
Any 和 object 的区别。与 Any 相似,所有类型都是 object 的子类型。然而,与 Any 不同,object 不可逆:object 不是 其它类型的子类型。
就是说,值的类型是 object 时,类型检查器几乎会拒绝所有对它的操作,并且,把它赋给更精确的类型变量(或返回值)属于类型错误。例如:
def hash_a(item: object) -> int:
# Fails; an object does not have a 'magic' method.
item.magic()
...
def hash_b(item: Any) -> int:
# Typechecks
item.magic()
...
# Typechecks, since ints and strs are subclasses of object
hash_a(42)
hash_a("foo")
# Typechecks, since Any is compatible with all types
hash_b(42)
hash_b("foo")
名义子类型 vs 结构子类型¶
PEP 484 最初只是把 Python 静态类型系统定义为应用 名义子类型。即,当且仅当 A 是 B 的子类时,才能在预期 B 类时应用 A 类。
此项要求以前也适用于抽象基类,例如,Iterable 。这种方式的问题在于,定义类时必须显式说明,既不 Pythonic,也不是动态类型式 Python 代码的惯用写法。例如,下列代码就遵从了 PEP 484 的规范:
from collections.abc import Sized, Iterable, Iterator
class Bucket(Sized, Iterable[int]):
...
def __len__(self) -> int: ...
def __iter__(self) -> Iterator[int]: ...
PEP 544 允许用户在类定义时不显式说明基类,从而解决了这一问题,静态类型检查器隐式认为 Bucket 既是 Sized 的子类型,又是 Iterable[int] 的子类型。这就是 结构子类型 (又称为静态鸭子类型):
from collections.abc import Iterator, Iterable
class Bucket: # Note: no base classes
...
def __len__(self) -> int: ...
def __iter__(self) -> Iterator[int]: ...
def collect(items: Iterable[int]) -> int: ...
result = collect(Bucket()) # Passes type check
此外,结构子类型的优势在于,通过继承特殊类 Protocol ,用户可以定义新的自定义协议(见下文中的例子)。
模块内容¶
本模块定义了下列类、函数和修饰器。
注解
本模块定义了一些类型,作为标准库中已有的类的子类,从而可以让 Generic 支持 [] 中的类型变量。Python 3.9 中,这些标准库的类已支持 [] ,因此,这些类型就变得冗余了。
Python 3.9 弃用了这些冗余类型,但解释器并未提供相应的弃用警告。标记弃用类型的工作留待支持 Python 3.9 及以上版本的类型检查器实现。
Python 3.9.0 发布五年后的首个 Python 发行版将从 typing 模块中移除这些弃用类型。详见 PEP 585 《标准集合的类型提示泛型》。
特殊类型原语¶
特殊类型¶
这些类型可用于类型注解,但不支持 []。
-
typing.NoReturn¶ 标记没有返回值的函数的特殊类型。例如:
from typing import NoReturn def stop() -> NoReturn: raise RuntimeError('no way')
3.5.4 新版功能.
3.6.2 新版功能.
特殊形式¶
可用于类型注解,且支持 [] ,每种形式都有其独特的句法。
-
typing.Tuple¶ 元组类型;
Tuple[X, Y]是二项元组类型,第一个元素的类型是 X,第二个元素的类型是 Y。空元组的类型可写为Tuple[()]。例:
Tuple[T1, T2]是二项元组,类型变量分别为 T1 和 T2。Tuple[int, float, str]是由整数、浮点数、字符串组成的三项元组。可用省略号字面量指定同质变长元组,例如,
Tuple[int, ...]。Tuple与Tuple[Any, ...]等价,也与tuple等价。3.9 版后已移除:
builtins.tuple现已支持[]。详见 PEP 585 与 Generic Alias Type。
-
typing.Union¶ 联合类型;
Union[X, Y]的意思是,非 X 即 Y。可用
Union[int, str]等形式定义联合类型。 具体如下:参数必须是某种类型,且至少有一个。
联合类型之联合类型会被展平,例如:
Union[Union[int, str], float] == Union[int, str, float]
单参数之联合类型就是该参数自身,例如:
Union[int] == int # The constructor actually returns int
冗余的参数会被跳过,例如:
Union[int, str, int] == Union[int, str]
比较联合类型,不涉及参数顺序,例如:
Union[int, str] == Union[str, int]
联合类型不能作为子类,也不能实例化。
不支持
Union[X][Y]这种写法。Optional[X]是Union[X, None]的缩写。
在 3.7 版更改: 在运行时,不要移除联合类型中的显式子类。
-
typing.Optional¶ 可选类型。
Optional[X]等价于Union[X, None]。注意,可选类型与含默认值的可选参数不同。含默认值的可选参数不需要在类型注解上添加
Optional限定符,因为它仅是可选的。例如:def foo(arg: int = 0) -> None: ...
另一方面,显式应用
None值时,不管该参数是否可选,Optional都适用。例如:def foo(arg: Optional[int] = None) -> None: ...
-
typing.Callable¶ 可调类型;
Callable[[int], str]是把(int)转为 str 的函数。下标句法必须与参数列表和返回类型这两个值一起使用。参数列表只能是类型列表或省略号;返回类型只能是单一类型。
没有说明可选参数或关键字参数的句法;这类函数类型很少用作回调类型。
Callable[..., ReturnType](省略号字面量)可用于为接受任意数量参数,并返回ReturnType的可调对象提供类型提示。纯Callable等价于Callable[..., Any],进而等价于collections.abc.Callable。3.9 版后已移除:
collections.abc.Callable现已支持[]。 详见 PEP 585 与 Generic Alias Type。
-
class
typing.Type(Generic[CT_co])¶ 用
C注解的变量可以接受类型C的值。反之,用Type[C]注解的变量可以接受类自身的值 — 准确地说,是接受C的 类对象,例如:a = 3 # Has type 'int' b = int # Has type 'Type[int]' c = type(a) # Also has type 'Type[int]'
注意,
Type[C]为协变量:class User: ... class BasicUser(User): ... class ProUser(User): ... class TeamUser(User): ... # Accepts User, BasicUser, ProUser, TeamUser, ... def make_new_user(user_class: Type[User]) -> User: # ... return user_class()
Type[C]为协变量的意思是指,C的所有子类都应使用与C相同的构造器签名及类方法签名。类型检查器应标记违反此项规定的内容,但也应允许符合指定基类构造器调用的子类进行构造器调用。PEP 484 修订版将来可能会调整类型检查器对这种特例的处理方式。Type合法的参数仅有类、Any、类型变量 以及上述类型的联合类型。例如:def new_non_team_user(user_class: Type[Union[BasicUser, ProUser]]): ...
Type[Any]等价于Type,进而等价于 Python 元类架构的根基,type。3.5.2 新版功能.
3.9 版后已移除:
builtins.type现已支持[]。详见 PEP 585 与 Generic Alias Type。
-
typing.Literal¶ 表示类型检查器对应变量或函数参数的值等价于给定字面量(或多个字面量之一)的类型。例如:
def validate_simple(data: Any) -> Literal[True]: # always returns True ... MODE = Literal['r', 'rb', 'w', 'wb'] def open_helper(file: str, mode: MODE) -> str: ... open_helper('/some/path', 'r') # Passes type check open_helper('/other/path', 'typo') # Error in type checker
Literal[...]不能创建子类。在运行时,任意值均可作为Literal[...]的类型参数,但类型检查器可以对此加以限制。字面量类型详见 PEP 586 。3.8 新版功能.
-
typing.ClassVar¶ 标记类变量的特殊类型构造器。
如 PEP 526 所述,打包在 ClassVar 内的变量注解是指,给定属性应当用作类变量,而不应设置在类实例上。用法如下:
class Starship: stats: ClassVar[dict[str, int]] = {} # class variable damage: int = 10 # instance variable
ClassVar仅接受类型,也不能使用下标。ClassVar本身不是类,不应用于isinstance()或issubclass()。ClassVar不改变 Python 运行时行为,但可以用于第三方类型检查器。例如,类型检查器会认为以下代码有错:enterprise_d = Starship(3000) enterprise_d.stats = {} # Error, setting class variable on instance Starship.stats = {} # This is OK
3.5.3 新版功能.
-
typing.Final¶ 告知类型检查器某名称不能再次赋值或在子类中重写的特殊类型构造器。例如:
MAX_SIZE: Final = 9000 MAX_SIZE += 1 # Error reported by type checker class Connection: TIMEOUT: Final[int] = 10 class FastConnector(Connection): TIMEOUT = 1 # Error reported by type checker
这些属性没有运行时检查。详见 PEP 591。
3.8 新版功能.
-
typing.Annotated¶ PEP 593 (
灵活函数和变量注解)里引入的类型,可以用上下文特定元数据(Annotated的参数可变,也可能用它的多个组成部分)装饰现有的类型。具体来说,就是类型提示Annotated[T, x]用元数据x注解类型T。静态分析或运行时都能使用该元数据。库(或工具)处理类型提示Annotated[T, x]时,在元数据x不涉及特殊逻辑的情况下,可忽略该类型提示,仅把它当作类型T。与typing模块中现有的no_type_check功能不同,该功能完全禁用了函数或类的类型检查注解,而Annotated类型则允许对T进行静态类型检查(例如,通过 mypy 或 Pyre,可安全地忽略x),也可以在特定应用程序中实现x的运行时访问。毕竟,如何解释注解(如有)由处理
Annotated类型的工具/库负责。工具/库处理Annotated类型时,扫描所有注解以确定是否需要进行处理(例如,使用isinstance())。工具/库不支持注解,或遇到未知注解时,应忽略注解,并把注解类型当作底层类型。
是否允许客户端在一个类型上使用多个注解,以及如何合并这些注解,由处理注解的工具决定。
Annotated类型支持把多个相同(或不同)的单个(或多个)类型注解置于任意节点。因此,使用这些注解的工具/库要负责处理潜在的重复项。例如,执行值范围分析时,应允许以下操作:T1 = Annotated[int, ValueRange(-10, 5)] T2 = Annotated[T1, ValueRange(-20, 3)]
传递
include_extras=True至get_type_hints(),即可在运行时访问额外的注解。语义详情:
Annotated的第一个参数必须是有效类型。支持多个类型标注(
Annotated支持可变参数):Annotated[int, ValueRange(3, 10), ctype("char")]
调用
Annotated至少要有两个参数(Annotated[int]是无效的)注解的顺序会被保留,且影响等价检查:
Annotated[int, ValueRange(3, 10), ctype("char")] != Annotated[ int, ctype("char"), ValueRange(3, 10) ]
嵌套
Annotated类型会被展平,元数据从最内层注解依序展开:Annotated[Annotated[int, ValueRange(3, 10)], ctype("char")] == Annotated[ int, ValueRange(3, 10), ctype("char") ]
不移除注解重复项:
Annotated[int, ValueRange(3, 10)] != Annotated[ int, ValueRange(3, 10), ValueRange(3, 10) ]
Annotated可用于嵌套或泛型别名:T = TypeVar('T') Vec = Annotated[list[tuple[T, T]], MaxLen(10)] V = Vec[int] V == Annotated[list[tuple[int, int]], MaxLen(10)]
3.9 新版功能.
构建泛型类型¶
以下内容是创建泛型类型的基石,但不在注解内使用。
-
class
typing.Generic¶ 用于泛型类型的抽象基类。
泛型类型一般通过继承含一个或多个类型变量的类实例进行声明。例如,泛型映射类型定义如下:
class Mapping(Generic[KT, VT]): def __getitem__(self, key: KT) -> VT: ... # Etc.
该类的用法如下:
X = TypeVar('X') Y = TypeVar('Y') def lookup_name(mapping: Mapping[X, Y], key: X, default: Y) -> Y: try: return mapping[key] except KeyError: return default
-
class
typing.TypeVar¶ 类型变量。
用法:
T = TypeVar('T') # Can be anything A = TypeVar('A', str, bytes) # Must be str or bytes
类型变量主要是为静态类型检查器提供支持,用于泛型类型与泛型函数定义的参数。有关泛型类型,详见
Generic。泛型函数的写法如下:def repeat(x: T, n: int) -> Sequence[T]: """Return a list containing n references to x.""" return [x]*n def longest(x: A, y: A) -> A: """Return the longest of two strings.""" return x if len(x) >= len(y) else y
本质上,后例的签名重载了
(str, str) -> str与(bytes, bytes) -> bytes。注意,参数是str子类的实例时,返回类型仍是纯str。在运行时,
isinstance(x, T)会触发TypeError异常。一般而言,isinstance()和issubclass()不应与类型搭配使用。通过
covariant=True或contravariant=True可以把类型变量标记为协变量或逆变量。详见 PEP 484。默认情况下,类型变量是不变量。类型变量还可以用bound=<type>指定上限。这里的意思是,(显式或隐式地)取代类型变量的实际类型必须是限定类型的子类,详见 PEP 484。
-
typing.AnyStr¶ AnyStr类型变量的定义为AnyStr = TypeVar('AnyStr', str, bytes)。这里指的是,它可以接受任意同类字符串,但不支持混用不同类别的字符串。例如:
def concat(a: AnyStr, b: AnyStr) -> AnyStr: return a + b concat(u"foo", u"bar") # Ok, output has type 'unicode' concat(b"foo", b"bar") # Ok, output has type 'bytes' concat(u"foo", b"bar") # Error, cannot mix unicode and bytes
-
class
typing.Protocol(Generic)¶ Protocol 类的基类。Protocol 类的定义如下:
class Proto(Protocol): def meth(self) -> int: ...
这些类主要与静态类型检查器搭配使用,用来识别结构子类型(静态鸭子类型),例如:
class C: def meth(self) -> int: return 0 def func(x: Proto) -> int: return x.meth() func(C()) # Passes static type check
详见 PEP 544。Protocol 类用
runtime_checkable()(见下文)装饰,忽略类型签名,仅检查给定属性是否存在,充当简要的运行时协议。Protocol 类可以是泛型,例如:
class GenProto(Protocol[T]): def meth(self) -> T: ...
3.8 新版功能.
-
@typing.runtime_checkable¶ 用于把 Protocol 类标记为运行时协议。
该协议可以与
isinstance()和issubclass()一起使用。应用于非协议的类时,会触发TypeError。该指令支持简易结构检查,与collections.abc的Iterable非常类似,只擅长做一件事。 例如:@runtime_checkable class Closable(Protocol): def close(self): ... assert isinstance(open('/some/file'), Closable)
注解
runtime_checkable()只检查所需方法是否存在,但却不检查类型签名! 例如,builtins.complex支持__float__(),因此,它能通过SupportsFloat的issubclass()检查。 然而,complex.__float__方法其实只是为了触发含更多信息的TypeError。3.8 新版功能.
其他特殊指令¶
这些特殊指令是声明类型的基石,但不在注解内使用。
-
class
typing.NamedTuple¶ collections.namedtuple()的类型版本。用法:
class Employee(NamedTuple): name: str id: int
相当于:
Employee = collections.namedtuple('Employee', ['name', 'id'])
为字段提供默认值,要在类体内赋值:
class Employee(NamedTuple): name: str id: int = 3 employee = Employee('Guido') assert employee.id == 3
带默认值的字段必须在不带默认值的字段后面。
生成的类具有
__annotations__这个附加属性,提供了映射字段名与字段类型的字典。(字段名在_fields属性内,默认值在_field_defaults属性内,这两项都是命名元组 API 的组成部分。)NamedTuple子类也支持文档字符串与方法:class Employee(NamedTuple): """Represents an employee.""" name: str id: int = 3 def __repr__(self) -> str: return f'<Employee {self.name}, id={self.id}>'
反向兼容用法:
Employee = NamedTuple('Employee', [('name', str), ('id', int)])
在 3.6 版更改: 添加了对 PEP 526 中变量注解句法的支持。
在 3.6.1 版更改: 添加了对默认值、方法、文档字符串的支持。
在 3.8 版更改:
_field_types和__annotations__属性现已使用常规字典,不再使用OrderedDict实例。在 3.9 版更改: 移除了
_field_types属性, 改用具有相同信息,但更标准的__annotations__属性。
-
typing.NewType(name, tp)¶ 用于为类型检查器标明不同类型的辅助函数,详见 NewType。在运行时,它返回一个返回其参数的函数。用法如下:
UserId = NewType('UserId', int) first_user = UserId(1)
3.5.2 新版功能.
-
class
typing.TypedDict(dict)¶ 把类型提示添加至字典的特殊构造器。在运行时,它是纯
dict。TypedDict声明一个字典类型,该类型预期所有实例都具有一组键集,其中,每个键都与对应类型的值关联。运行时不检查此预期,而是由类型检查器强制执行。用法如下:class Point2D(TypedDict): x: int y: int label: str a: Point2D = {'x': 1, 'y': 2, 'label': 'good'} # OK b: Point2D = {'z': 3, 'label': 'bad'} # Fails type check assert Point2D(x=1, y=2, label='first') == dict(x=1, y=2, label='first')
用于内省的类型信息可通过
Point2D.__annotations__和Point2D.__total__访问。为了让不支持 PEP 526 的老版 Python 也能使用此功能,TypedDict支持两个附加的等价句法形式:Point2D = TypedDict('Point2D', x=int, y=int, label=str) Point2D = TypedDict('Point2D', {'x': int, 'y': int, 'label': str})
默认情况下,所有键都必须列在 TypedDict 里。不过,也可以通过指定 total 参数进行重写。用法如下:
class point2D(TypedDict, total=False): x: int y: int
这段代码的意思是,可以省略 point2D 这个 TypedDict 中的任意键。类型检查器只支持字面量 False 或 True 作为 total 参数的值。True 是默认值,表明在类体中,必须定义所有项目。
更多示例与
TypedDict的详细规则,详见 PEP 589。3.8 新版功能.
泛型具象容器¶
对应的内置类型¶
-
class
typing.Dict(dict, MutableMapping[KT, VT])¶ dict的泛型版本。适用于注解返回类型。注解参数时,最好使用Mapping等抽象容器类型。该类型用法如下:
def count_words(text: str) -> Dict[str, int]: ...
3.9 版后已移除:
builtins.dict现已支持[]。详见 PEP 585 和 Generic Alias Type。
-
class
typing.List(list, MutableSequence[T])¶ list的泛型版本。适用于注解返回类型。注解参数时,最好使用Sequence或Iterable等抽象容器类型。该类型用法如下:
T = TypeVar('T', int, float) def vec2(x: T, y: T) -> List[T]: return [x, y] def keep_positives(vector: Sequence[T]) -> List[T]: return [item for item in vector if item > 0]
3.9 版后已移除:
builtins.list现已支持[]。详见 PEP 585 与 Generic Alias Type。
-
class
typing.Set(set, MutableSet[T])¶ builtins.set的泛型版本。适用于注解返回类型。注解参数时,最好使用AbstractSet等抽象容器类型。3.9 版后已移除:
builtins.set现已支持[]。详见 PEP 585 和 Generic Alias Type。
-
class
typing.FrozenSet(frozenset, AbstractSet[T_co])¶ builtins.frozenset的泛型版本。3.9 版后已移除:
builtins.frozenset现已支持[]。详见 PEP 585 和 Generic Alias Type。
注解
Tuple 是一种特殊形式。
collections 对应类型¶
-
class
typing.DefaultDict(collections.defaultdict, MutableMapping[KT, VT])¶ collections.defaultdict的泛型版本。3.5.2 新版功能.
3.9 版后已移除:
collections.defaultdict现已支持[]。详见 PEP 585 与 Generic Alias Type。
-
class
typing.OrderedDict(collections.OrderedDict, MutableMapping[KT, VT])¶ collections.OrderedDict的泛型版本。3.7.2 新版功能.
3.9 版后已移除:
collections.OrderedDict现已支持[]。详见 PEP 585 与 Generic Alias Type。
-
class
typing.ChainMap(collections.ChainMap, MutableMapping[KT, VT])¶ collections.ChainMap的泛型版本。3.5.4 新版功能.
3.6.1 新版功能.
3.9 版后已移除:
collections.ChainMap现已支持[]。详见 PEP 585 和 Generic Alias Type。
-
class
typing.Counter(collections.Counter, Dict[T, int])¶ collections.Counter的泛型版本。3.5.4 新版功能.
3.6.1 新版功能.
3.9 版后已移除:
collections.Counter现已支持[]。详见 PEP 585 和 Generic Alias Type。
-
class
typing.Deque(deque, MutableSequence[T])¶ collections.deque的泛型版本。3.5.4 新版功能.
3.6.1 新版功能.
3.9 版后已移除:
collections.deque现已支持[]。详见 PEP 585 和 Generic Alias Type。
其他具象类型¶
-
class
typing.IO¶ -
class
typing.TextIO¶ -
class
typing.BinaryIO¶ 泛型类型
IO[AnyStr]及其子类TextIO(IO[str])与BinaryIO(IO[bytes])表示 I/O 流的类型,例如open()所返回的对象。Deprecated since version 3.8, will be removed in version 3.12: 这些类型也在
typing.io命名空间中,它从未得到类型检查器的支持并将被移除。
-
class
typing.Pattern¶ -
class
typing.Match¶ 这些类型对应的是从
re.compile()和re.match()返回的类型。 这些类型(及相应的函数)是AnyStr中的泛型并可通过编写Pattern[str],Pattern[bytes],Match[str]或Match[bytes]来具体指定。Deprecated since version 3.8, will be removed in version 3.12: 这些类型也在
typing.re命名空间中,它从未得到类型检查器的支持并将被移除。3.9 版后已移除:
re模块中的Pattern与Match类现已支持[]。详见 PEP 585 与 Generic Alias Type。
-
class
typing.Text¶ Text是str的别名。提供了对 Python 2 代码的向下兼容:Python 2 中,Text是unicode的别名。使用
Text时,值中必须包含 unicode 字符串,以兼容 Python 2 和 Python 3:def add_unicode_checkmark(text: Text) -> Text: return text + u' \u2713'
3.5.2 新版功能.
抽象基类¶
collections.abc 对应的容器¶
-
class
typing.AbstractSet(Sized, Collection[T_co])¶ collections.abc.Set的泛型版本。3.9 版后已移除:
collections.abc.Set现已支持[]。详见 PEP 585 与 Generic Alias Type。
-
class
typing.ByteString(Sequence[int])¶ collections.abc.ByteString的泛型版本。该类型代表了
bytes、bytearray、memoryview等字节序列类型。作为该类型的简称,
bytes可用于标注上述任意类型的参数。3.9 版后已移除:
collections.abc.ByteString现已支持[]。详见 PEP 585 与 Generic Alias Type。
-
class
typing.Collection(Sized, Iterable[T_co], Container[T_co])¶ collections.abc.Collection的泛型版本。3.6.0 新版功能.
3.9 版后已移除:
collections.abc.Collection现已支持[]。详见 PEP 585 与 Generic Alias Type。
-
class
typing.Container(Generic[T_co])¶ collections.abc.Container的泛型版本。3.9 版后已移除:
collections.abc.Container现已支持[]。详见 PEP 585 和 Generic Alias Type。
-
class
typing.ItemsView(MappingView, Generic[KT_co, VT_co])¶ collections.abc.ItemsView的泛型版本。3.9 版后已移除:
collections.abc.ItemsView现已支持[]。详见 PEP 585 和 Generic Alias Type。
-
class
typing.KeysView(MappingView[KT_co], AbstractSet[KT_co])¶ collections.abc.KeysView的泛型版本。3.9 版后已移除:
collections.abc.KeysView现已支持[]。详见 PEP 585 和 Generic Alias Type。
-
class
typing.Mapping(Sized, Collection[KT], Generic[VT_co])¶ collections.abc.Mapping的泛型版本。用法如下:def get_position_in_index(word_list: Mapping[str, int], word: str) -> int: return word_list[word]
3.9 版后已移除:
collections.abc.Mapping现已支持[]。详见 PEP 585 和 Generic Alias Type。
-
class
typing.MappingView(Sized, Iterable[T_co])¶ collections.abc.MappingView的泛型版本。3.9 版后已移除:
collections.abc.MappingView现已支持[]。详见 PEP 585 和 Generic Alias Type。
-
class
typing.MutableMapping(Mapping[KT, VT])¶ collections.abc.MutableMapping的泛型版本。3.9 版后已移除:
collections.abc.MutableMapping现已支持[]。详见 PEP 585 和 Generic Alias Type。
-
class
typing.MutableSequence(Sequence[T])¶ collections.abc.MutableSequence的泛型版本。3.9 版后已移除:
collections.abc.MutableSequence现已支持[]。详见 PEP 585 和 Generic Alias Type。
-
class
typing.MutableSet(AbstractSet[T])¶ collections.abc.MutableSet的泛型版本。3.9 版后已移除:
collections.abc.MutableSet现已支持[]。详见 PEP 585 和 Generic Alias Type。
-
class
typing.Sequence(Reversible[T_co], Collection[T_co])¶ collections.abc.Sequence的泛型版本。3.9 版后已移除:
collections.abc.Sequence现已支持[]。详见 PEP 585 和 Generic Alias Type。
-
class
typing.ValuesView(MappingView[VT_co])¶ collections.abc.ValuesView的泛型版本。3.9 版后已移除:
collections.abc.ValuesView现已支持[]。详见 PEP 585 和 Generic Alias Type。
collections.abc 对应的其他类型¶
-
class
typing.Iterable(Generic[T_co])¶ collections.abc.Iterable的泛型版本。3.9 版后已移除:
collections.abc.Iterable现已支持[]。详见 PEP 585 和 Generic Alias Type。
-
class
typing.Iterator(Iterable[T_co])¶ collections.abc.Iterator的泛型版本。3.9 版后已移除:
collections.abc.Iterator现已支持[]。详见 PEP 585 和 Generic Alias Type。
-
class
typing.Generator(Iterator[T_co], Generic[T_co, T_contra, V_co])¶ 生成器可以由泛型类型
Generator[YieldType, SendType, ReturnType]注解。例如:def echo_round() -> Generator[int, float, str]: sent = yield 0 while sent >= 0: sent = yield round(sent) return 'Done'
注意,与 typing 模块里的其他泛型不同,
Generator的SendType属于逆变行为,不是协变行为,也是不变行为。如果生成器只产生值,可将
SendType与ReturnType设为None:def infinite_stream(start: int) -> Generator[int, None, None]: while True: yield start start += 1
此外,还可以把生成器的返回类型注解为
Iterable[YieldType]或Iterator[YieldType]:def infinite_stream(start: int) -> Iterator[int]: while True: yield start start += 1
3.9 版后已移除:
collections.abc.Generator现已支持[]。详见 PEP 585 和 Generic Alias Type。
-
class
typing.Hashable¶
-
class
typing.Reversible(Iterable[T_co])¶ collections.abc.Reversible的泛型版本。3.9 版后已移除:
collections.abc.Reversible现已支持[]。详见 PEP 585 和 Generic Alias Type。
-
class
typing.Sized¶
异步编程¶
-
class
typing.Coroutine(Awaitable[V_co], Generic[T_co, T_contra, V_co])¶ collections.abc.Coroutine的泛型版本。类型变量的差异和顺序与Generator的内容相对应,例如:from collections.abc import Coroutine c = None # type: Coroutine[list[str], str, int] ... x = c.send('hi') # type: list[str] async def bar() -> None: x = await c # type: int
3.5.3 新版功能.
3.9 版后已移除:
collections.abc.Coroutine现已支持[]。详见 PEP 585 和 Generic Alias Type。
-
class
typing.AsyncGenerator(AsyncIterator[T_co], Generic[T_co, T_contra])¶ 异步生成器可由泛型类型
AsyncGenerator[YieldType, SendType]注解。例如:async def echo_round() -> AsyncGenerator[int, float]: sent = yield 0 while sent >= 0.0: rounded = await round(sent) sent = yield rounded
与常规生成器不同,异步生成器不能返回值,因此没有
ReturnType类型参数。 与Generator类似,SendType也属于逆变行为。如果生成器只产生值,可将
SendType设置为None:async def infinite_stream(start: int) -> AsyncGenerator[int, None]: while True: yield start start = await increment(start)
此外,可用
AsyncIterable[YieldType]或AsyncIterator[YieldType]注解生成器的返回类型:async def infinite_stream(start: int) -> AsyncIterator[int]: while True: yield start start = await increment(start)
3.6.1 新版功能.
3.9 版后已移除:
collections.abc.AsyncGenerator现已支持[]。详见 PEP 585 和 Generic Alias Type。
-
class
typing.AsyncIterable(Generic[T_co])¶ collections.abc.AsyncIterable的泛型版本。3.5.2 新版功能.
3.9 版后已移除:
collections.abc.AsyncIterable现已支持[]。详见 PEP 585 和 Generic Alias Type。
-
class
typing.AsyncIterator(AsyncIterable[T_co])¶ collections.abc.AsyncIterator的泛型版本。3.5.2 新版功能.
3.9 版后已移除:
collections.abc.AsyncIterator现已支持[]。详见 PEP 585 和 Generic Alias Type。
-
class
typing.Awaitable(Generic[T_co])¶ collections.abc.Awaitable的泛型版本。3.5.2 新版功能.
3.9 版后已移除:
collections.abc.Awaitable现已支持[]。详见 PEP 585 和 Generic Alias Type。
上下文管理器类型¶
-
class
typing.ContextManager(Generic[T_co])¶ contextlib.AbstractContextManager的泛型版本。3.5.4 新版功能.
3.6.0 新版功能.
3.9 版后已移除:
contextlib.AbstractContextManager现已支持[]。详见 PEP 585 和 Generic Alias Type。
-
class
typing.AsyncContextManager(Generic[T_co])¶ contextlib.AbstractAsyncContextManager的泛型版本。3.5.4 新版功能.
3.6.2 新版功能.
3.9 版后已移除:
contextlib.AbstractAsyncContextManager现已支持[]。详见 PEP 585 和 Generic Alias Type。
协议¶
这些协议由 runtime_checkable() 装饰。
-
class
typing.SupportsAbs¶ 含抽象方法
__abs__的抽象基类,是其返回类型里的协变量。
-
class
typing.SupportsBytes¶ 含抽象方法
__bytes__的抽象基类。
-
class
typing.SupportsComplex¶ 含抽象方法
__complex__的抽象基类。
-
class
typing.SupportsFloat¶ 含抽象方法
__float__的抽象基类。
-
class
typing.SupportsIndex¶ 含抽象方法
__index__的抽象基类。3.8 新版功能.
-
class
typing.SupportsInt¶ 含抽象方法
__int__的抽象基类。
-
class
typing.SupportsRound¶ 含抽象方法
__round__的抽象基类,是其返回类型的协变量。
函数与装饰器¶
-
typing.cast(typ, val)¶ 把值强制转换为类型。
不变更返回值。对类型检查器而言,代表了返回值具有指定的类型,但运行时故意不做任何检查(以便让检查速度尽量快)。
-
@typing.overload¶ @overload装饰器可以修饰支持多个不同参数类型组合的函数或方法。@overload- 装饰定义的系列必须紧跟一个非@overload-装饰定义(用于同一个函数/方法)。@overload-装饰定义仅是为了协助类型检查器, 因为该装饰器会被非@overload-装饰定义覆盖,后者用于运行时,而且会被类型检查器忽略。在运行时直接调用@overload装饰的函数会触发NotImplementedError。下面的重载示例给出了比联合类型或类型变量更精准的类型:@overload def process(response: None) -> None: ... @overload def process(response: int) -> tuple[int, str]: ... @overload def process(response: bytes) -> str: ... def process(response): <actual implementation>
详见 PEP 484,与其他类型语义进行对比。
-
@typing.final¶ 告知类型检查器被装饰的方法不能被覆盖,且被装饰的类不能作为子类的装饰器,例如:
class Base: @final def done(self) -> None: ... class Sub(Base): def done(self) -> None: # Error reported by type checker ... @final class Leaf: ... class Other(Leaf): # Error reported by type checker ...
这些属性没有运行时检查。详见 PEP 591。
3.8 新版功能.
-
@typing.no_type_check¶ 标明注解不是类型提示的装饰器。
用作类或函数的 decorator。用于类时,递归地应用于该类中定义的所有方法,(但不影响超类或子类中定义的方法)。
本方法可直接修改函数。
-
@typing.no_type_check_decorator¶ 让其他装饰器具有
no_type_check()效果的装饰器。本装饰器用
no_type_check()里的装饰函数打包其他装饰器。
-
@typing.type_check_only¶ 标记类或函数内不可用于运行时的装饰器。
在运行时,该装饰器本身不可用。实现返回的是私有类实例时,它主要是用于标记在类型存根文件中定义的类。
@type_check_only class Response: # private or not available at runtime code: int def get_header(self, name: str) -> str: ... def fetch_response() -> Response: ...
注意,建议不要返回私有类实例,最好将之设为公共类。
内省辅助器¶
-
typing.get_type_hints(obj, globalns=None, localns=None, include_extras=False)¶ 返回函数、方法、模块、类对象的类型提示的字典。
一般情况下,与
obj.__annotations__相同。此外,可通过在globals与locals命名空间里进行评估,以此来处理编码为字符串字面量的前向引用。如有需要,在默认值设置为None时,可为函数或方法注解添加Optional[t]。对于类C,则返回由所有__annotations__与C.__mro__逆序合并而成的字典。本函数以递归地方式用
T替换所有Annotated[T, ...], 除非将include_extras的值设置为True(详见Annotated)。例如:class Student(NamedTuple): name: Annotated[str, 'some marker'] get_type_hints(Student) == {'name': str} get_type_hints(Student, include_extras=False) == {'name': str} get_type_hints(Student, include_extras=True) == { 'name': Annotated[str, 'some marker'] }
在 3.9 版更改: PEP 593 的组成部分,添加了
include_extras参数。
-
typing.get_args(tp)¶
-
typing.get_origin(tp)¶ 为泛型类型与特殊类型形式提供了基本的内省功能。
对于
X[Y, Z, ...]形式的类型对象,这些函数返回X与(Y, Z, ...)。如果X是内置对象或collectionsclass 的泛型别名, 会将其标准化为原始类。如果X是包含在其他泛型类型中的Union或Literal,(Y, Z, ...)的顺序会因类型缓存,而与原始参数[Y, Z, ...]的顺序不同。对于不支持的对象会相应地返回None或()。例如:assert get_origin(Dict[str, int]) is dict assert get_args(Dict[int, str]) == (int, str) assert get_origin(Union[int, str]) is Union assert get_args(Union[int, str]) == (int, str)
3.8 新版功能.
常量¶
-
typing.TYPE_CHECKING¶ 被第三方静态类型检查器假定为
True的特殊常量。在运行时为False。用法如下:if TYPE_CHECKING: import expensive_mod def fun(arg: 'expensive_mod.SomeType') -> None: local_var: expensive_mod.AnotherType = other_fun()
第一个类型注解必须用引号标注,才能把它当作“前向引用”,从而在解释器运行时中隐藏
expensive_mod引用。局部变量的类型注释不会被评估,因此,第二个注解不需要用引号引起来。注解
Python 3.7 或更高版本中使用
from __future__ import时,函数定义时不处理注解, 而是把注解当作字符串存在__annotations__里,这样就不必为注解使用引号。(详见 PEP 563)。3.5.2 新版功能.
