typing
--- 類(lèi)型提示支持?
3.5 新版功能.
源碼: Lib/typing.py
備注
Python 運行時(shí)不強制執行函數和變量類(lèi)型注解,但這些注解可用于類(lèi)型檢查器、IDE、靜態(tài)檢查器等第三方工具。
This module provides runtime support for type hints. The most fundamental
support consists of the types Any
, Union
, Callable
,
TypeVar
, and Generic
. For a full specification, please see
PEP 484. For a simplified introduction to type hints, see PEP 483.
下面的函數接收與返回的都是字符串,注解方式如下:
def greeting(name: str) -> str:
return 'Hello ' + name
greeting
函數中,參數 name
的類(lèi)型是 str
,返回類(lèi)型也是 str
。子類(lèi)型也可以當作參數。
New features are frequently added to the typing
module.
The typing_extensions package
provides backports of these new features to older versions of Python.
For a summary of deprecated features and a deprecation timeline, please see Deprecation Timeline of Major Features.
Relevant PEPs?
Since the initial introduction of type hints in PEP 484 and PEP 483, a number of PEPs have modified and enhanced Python's framework for type annotations. These include:
- PEP 544: Protocols: Structural subtyping (static duck typing)
Introducing
Protocol
and the@runtime_checkable
decorator
- PEP 585: Type Hinting Generics In Standard Collections
Introducing
types.GenericAlias
and the ability to use standard library classes as generic types
- PEP 604: Allow writing union types as
X | Y
Introducing
types.UnionType
and the ability to use the binary-or operator|
to signify a union of types
- PEP 604: Allow writing union types as
- PEP 612: Parameter Specification Variables
Introducing
ParamSpec
andConcatenate
- PEP 646: Variadic Generics
Introducing
TypeVarTuple
- PEP 675: Arbitrary Literal String Type
Introducing
LiteralString
類(lèi)型別名?
把類(lèi)型賦給別名,就可以定義類(lèi)型別名。本例中,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])
類(lèi)型別名適用于簡(jiǎn)化復雜的類(lèi)型簽名。例如:
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
是一種類(lèi)型提示特例,已被 type(None)
取代。
NewType?
Use the NewType
helper to create distinct types:
from typing import NewType
UserId = NewType('UserId', int)
some_id = UserId(524313)
靜態(tài)類(lèi)型檢查器把新類(lèi)型當作原始類(lèi)型的子類(lèi),這種方式適用于捕捉邏輯錯誤:
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
類(lèi)型的變量可執行所有 int
操作,但返回結果都是 int
類(lèi)型。這種方式允許在預期 int
時(shí)傳入 UserId
,還能防止意外創(chuàng )建無(wú)效的 UserId
:
# 'output' is of type 'int', not 'UserId'
output = UserId(23413) + UserId(54341)
Note that these checks are enforced only by the static type checker. At runtime,
the statement Derived = NewType('Derived', Base)
will make Derived
a
callable that immediately returns whatever parameter you pass it. That means
the expression Derived(some_value)
does not create a new class or introduce
much overhead beyond that of a regular function call.
更確切地說(shuō),在運行時(shí),some_value is Derived(some_value)
表達式總為 True。
創(chuàng )建 Derived
的子類(lèi)型是無(wú)效的:
from typing import NewType
UserId = NewType('UserId', int)
# Fails at runtime and does not typecheck
class AdminUserId(UserId): pass
然而,我們可以在 "派生的" NewType
的基礎上創(chuàng )建一個(gè) NewType
。
from typing import NewType
UserId = NewType('UserId', int)
ProUserId = NewType('ProUserId', UserId)
同時(shí),ProUserId
的類(lèi)型檢查也可以按預期執行。
詳見(jiàn) PEP 484。
備注
回顧上文,類(lèi)型別名聲明了兩種彼此 等價(jià) 的類(lèi)型。 Alias = Original
時(shí),靜態(tài)類(lèi)型檢查器認為 Alias
與 Original
完全等價(jià)。 這種方式適用于簡(jiǎn)化復雜類(lèi)型簽名。
反之,NewType
聲明把一種類(lèi)型當作另一種類(lèi)型的 子類(lèi)型。Derived = NewType('Derived', Original)
時(shí),靜態(tài)類(lèi)型檢查器把 Derived
當作 Original
的 子類(lèi) ,即,Original
類(lèi)型的值不能用在預期 Derived
類(lèi)型的位置。這種方式適用于以最小運行時(shí)成本防止邏輯錯誤。
3.5.2 新版功能.
在 3.10 版更改: NewType
現在是一個(gè)類(lèi)而不是一個(gè)函數。 在調用 NewType
而不是普通的函數時(shí),會(huì )有一些額外的運行時(shí)間成本。 然而,這種開(kāi)銷(xiāo)將在 3.11.0 中減少。
可調對象(Callable)?
預期特定簽名回調函數的框架可以用 Callable[[Arg1Type, Arg2Type], ReturnType]
實(shí)現類(lèi)型提示。
例如:
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
async def on_update(value: str) -> None:
# Body
callback: Callable[[str], Awaitable[None]] = on_update
無(wú)需指定調用簽名,用省略號字面量替換類(lèi)型提示里的參數列表: Callable[..., ReturnType]
,就可以聲明可調對象的返回類(lèi)型。
以其他可調用對象為參數的可調用對象可以使用 ParamSpec
來(lái)表明其參數類(lèi)型是相互依賴(lài)的。此外,如果該可調用對象增加或刪除了其他可調用對象的參數,可以使用 Concatenate
操作符。 它們分別采取``Callable[ParamSpecVariable, ReturnType]`` 和 Callable[Concatenate[Arg1Type, Arg2Type, ..., ParamSpecVariable], ReturnType]
的形式。
在 3.10 版更改: Callable
現在支持 ParamSpec
和 Concatenate
。 更多信息見(jiàn) PEP 612。
參見(jiàn)
The documentation for ParamSpec
and Concatenate
provides
examples of usage in Callable
.
泛型(Generic)?
容器中,對象的類(lèi)型信息不能以泛型方式靜態(tài)推斷,因此,抽象基類(lèi)擴展支持下標,用于表示容器元素的預期類(lèi)型。
from collections.abc import Mapping, Sequence
def notify_by_email(employees: Sequence[Employee],
overrides: Mapping[str, str]) -> None: ...
Generics can be parameterized by using a factory available in typing
called 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]
用戶(hù)定義的泛型類(lèi)型?
用戶(hù)定義的類(lèi)可以定義為泛型類(lèi)。
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]
是定義類(lèi) LoggedVar
的基類(lèi),該類(lèi)使用單類(lèi)型參數 T
。在該類(lèi)體內,T
是有效的類(lèi)型。
The Generic
base class defines __class_getitem__()
so
that LoggedVar[t]
is valid as a type:
from collections.abc import Iterable
def zero_all_vars(vars: Iterable[LoggedVar[int]]) -> None:
for var in vars:
var.set(0)
A generic type can have any number of type variables. All varieties of
TypeVar
are permissible as parameters for a generic type:
from typing import TypeVar, Generic, Sequence
T = TypeVar('T', contravariant=True)
B = TypeVar('B', bound=Sequence[bytes], covariant=True)
S = TypeVar('S', int, str)
class WeirdTrio(Generic[T, B, S]):
...
Generic
類(lèi)型變量的參數應各不相同。下列代碼就是無(wú)效的:
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]):
...
繼承自泛型類(lèi)時(shí),可以修正某些類(lèi)型變量:
from collections.abc import Mapping
from typing import TypeVar
T = TypeVar('T')
class MyDict(Mapping[str, T]):
...
比如,本例中 MyDict
調用的單參數,T
。
未指定泛型類(lèi)的類(lèi)型參數時(shí),每個(gè)位置的類(lèi)型都預設為 Any
。下例中,MyIterable
不是泛型,但卻隱式繼承了 Iterable[Any]
:
from collections.abc import Iterable
class MyIterable(Iterable): # Same as Iterable[Any]
還支持用戶(hù)定義的泛型類(lèi)型別名。例如:
from collections.abc import Iterable
from typing import TypeVar
S = TypeVar('S')
Response = Iterable[S] | int
# Return type here is same as 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
不再支持自定義元類(lèi)。
用戶(hù)定義的參數表達式的泛型也通過(guò) Generic[P]
形式的參數規范變量來(lái)支持。該行為與上面描述的類(lèi)型變量一致,因為參數規范變量被類(lèi)型化模塊視為一個(gè)專(zhuān)門(mén)的類(lèi)型變量。 這方面的一個(gè)例外是,一個(gè)類(lèi)型列表可以用來(lái)替代 ParamSpec
:
>>> from typing import Generic, ParamSpec, TypeVar
>>> T = TypeVar('T')
>>> P = ParamSpec('P')
>>> class Z(Generic[T, P]): ...
...
>>> Z[int, [dict, float]]
__main__.Z[int, (<class 'dict'>, <class 'float'>)]
Furthermore, a generic with only one parameter specification variable will accept
parameter lists in the forms X[[Type1, Type2, ...]]
and also
X[Type1, Type2, ...]
for aesthetic reasons. Internally, the latter is converted
to the former, so the following are equivalent:
>>> class X(Generic[P]): ...
...
>>> X[int, str]
__main__.X[(<class 'int'>, <class 'str'>)]
>>> X[[int, str]]
__main__.X[(<class 'int'>, <class 'str'>)]
請注意,帶有 ParamSpec
的泛型在某些情況下可能不會(huì )有正確的``__parameters__``,因為它們主要用于靜態(tài)類(lèi)型檢查。
抽象基類(lèi)可作為用戶(hù)定義的泛型類(lèi)的基類(lèi),且不會(huì )與元類(lèi)沖突?,F已不再支持泛型元類(lèi)。參數化泛型的輸出結果會(huì )被緩存,typing 模塊的大多數類(lèi)型都可哈希、可進(jìn)行等價(jià)對比。
Any
類(lèi)型?
Any
是一種特殊的類(lèi)型。靜態(tài)類(lèi)型檢查器認為所有類(lèi)型均與 Any
兼容,同樣,Any
也與所有類(lèi)型兼容。
也就是說(shuō),可對 Any
類(lèi)型的值執行任何操作或方法調用,并賦值給任意變量:
from typing import Any
a: Any = None
a = [] # OK
a = 2 # OK
s: 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
類(lèi)型的值賦給更精確的類(lèi)型時(shí),不執行類(lèi)型檢查。例如,把 a
賦給 s
,在運行時(shí),即便 s
已聲明為 str
類(lèi)型,但接收 int
值時(shí),靜態(tài)類(lèi)型檢查器也不會(huì )報錯。
此外,未指定返回值與參數類(lèi)型的函數,都隱式地默認使用 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
需要混用動(dòng)態(tài)與靜態(tài)類(lèi)型代碼時(shí),此操作把 Any
當作 應急出口。
Any
和 object
的區別。與 Any
相似,所有類(lèi)型都是 object
的子類(lèi)型。然而,與 Any
不同,object 不可逆:object
不是 其它類(lèi)型的子類(lèi)型。
就是說(shuō),值的類(lèi)型是 object
時(shí),類(lèi)型檢查器幾乎會(huì )拒絕所有對它的操作,并且,把它賦給更精確的類(lèi)型變量(或返回值)屬于類(lèi)型錯誤。例如:
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")
使用 object
,說(shuō)明值能以類(lèi)型安全的方式轉為任何類(lèi)型。使用 Any
,說(shuō)明值是動(dòng)態(tài)類(lèi)型。
名義子類(lèi)型 vs 結構子類(lèi)型?
Initially PEP 484 defined the Python static type system as using
nominal subtyping. This means that a class A
is allowed where
a class B
is expected if and only if A
is a subclass of B
.
此項要求以前也適用于抽象基類(lèi),例如,Iterable
。這種方式的問(wèn)題在于,定義類(lèi)時(shí)必須顯式說(shuō)明,既不 Pythonic,也不是動(dòng)態(tài)類(lèi)型式 Python 代碼的慣用寫(xiě)法。例如,下列代碼就遵從了 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 允許用戶(hù)在類(lèi)定義時(shí)不顯式說(shuō)明基類(lèi),從而解決了這一問(wèn)題,靜態(tài)類(lèi)型檢查器隱式認為 Bucket
既是 Sized
的子類(lèi)型,又是 Iterable[int]
的子類(lèi)型。這就是 結構子類(lèi)型 (又稱(chēng)為靜態(tài)鴨子類(lèi)型):
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
此外,結構子類(lèi)型的優(yōu)勢在于,通過(guò)繼承特殊類(lèi) Protocol
,用戶(hù)可以定義新的自定義協(xié)議(見(jiàn)下文中的例子)。
模塊內容?
本模塊定義了下列類(lèi)、函數和修飾器。
備注
本模塊定義了一些類(lèi)型,作為標準庫中已有的類(lèi)的子類(lèi),從而可以讓 Generic
支持 []
中的類(lèi)型變量。Python 3.9 中,這些標準庫的類(lèi)已支持 []
,因此,這些類(lèi)型就變得冗余了。
Python 3.9 棄用了這些冗余類(lèi)型,但解釋器并未提供相應的棄用警告。標記棄用類(lèi)型的工作留待支持 Python 3.9 及以上版本的類(lèi)型檢查器實(shí)現。
Python 3.9.0 發(fā)布五年后的首個(gè) Python 發(fā)行版將從 typing
模塊中移除這些棄用類(lèi)型。詳見(jiàn) PEP 585 《標準集合的類(lèi)型提示泛型》。
特殊類(lèi)型原語(yǔ)?
特殊類(lèi)型?
這些類(lèi)型可用于類(lèi)型注解,但不支持 []
。
- typing.Any?
不受限的特殊類(lèi)型。
在 3.11 版更改:
Any
can now be used as a base class. This can be useful for avoiding type checker errors with classes that can duck type anywhere or are highly dynamic.
- typing.LiteralString?
Special type that includes only literal strings. A string literal is compatible with
LiteralString
, as is anotherLiteralString
, but an object typed as juststr
is not. A string created by composingLiteralString
-typed objects is also acceptable as aLiteralString
.Example:
def run_query(sql: LiteralString) -> ... ... def caller(arbitrary_string: str, literal_string: LiteralString) -> None: run_query("SELECT * FROM students") # ok run_query(literal_string) # ok run_query("SELECT * FROM " + literal_string) # ok run_query(arbitrary_string) # type checker error run_query( # type checker error f"SELECT * FROM students WHERE name = {arbitrary_string}" )
This is useful for sensitive APIs where arbitrary user-generated strings could generate problems. For example, the two cases above that generate type checker errors could be vulnerable to an SQL injection attack.
3.11 新版功能.
- typing.Never?
The bottom type, a type that has no members.
This can be used to define a function that should never be called, or a function that never returns:
from typing import Never def never_call_me(arg: Never) -> None: pass def int_or_str(arg: int | str) -> None: never_call_me(arg) # type checker error match arg: case int(): print("It's an int") case str(): print("It's a str") case _: never_call_me(arg) # ok, arg is of type Never
3.11 新版功能: On older Python versions,
NoReturn
may be used to express the same concept.Never
was added to make the intended meaning more explicit.
- typing.NoReturn?
標記沒(méi)有返回值的函數的特殊類(lèi)型。例如:
from typing import NoReturn def stop() -> NoReturn: raise RuntimeError('no way')
NoReturn
can also be used as a bottom type, a type that has no values. Starting in Python 3.11, theNever
type should be used for this concept instead. Type checkers should treat the two equivalently.3.5.4 新版功能.
3.6.2 新版功能.
- typing.Self?
Special type to represent the current enclosed class. For example:
from typing import Self class Foo: def returns_self(self) -> Self: ... return self
This annotation is semantically equivalent to the following, albeit in a more succinct fashion:
from typing import TypeVar Self = TypeVar("Self", bound="Foo") class Foo: def returns_self(self: Self) -> Self: ... return self
In general if something currently follows the pattern of:
class Foo: def return_self(self) -> "Foo": ... return self
You should use use
Self
as calls toSubclassOfFoo.returns_self
would haveFoo
as the return type and notSubclassOfFoo
.Other common use cases include:
classmethod
s that are used as alternative constructors and return instances of thecls
parameter.Annotating an
__enter__()
method which returns self.
For more information, see PEP 673.
3.11 新版功能.
特殊形式?
可用于類(lèi)型注解,且支持 []
,每種形式都有其獨特的句法。
- typing.Tuple?
元組類(lèi)型;
Tuple[X, Y]
是二項元組類(lèi)型,第一個(gè)元素的類(lèi)型是 X,第二個(gè)元素的類(lèi)型是 Y??赵M的類(lèi)型可寫(xiě)為Tuple[()]
。例:
Tuple[T1, T2]
是二項元組,類(lèi)型變量分別為 T1 和 T2。Tuple[int, float, str]
是由整數、浮點(diǎn)數、字符串組成的三項元組。可用省略號字面量指定同質(zhì)變長(cháng)元組,例如,
Tuple[int, ...]
。Tuple
與Tuple[Any, ...]
等價(jià),也與tuple
等價(jià)。3.9 版后已移除:
builtins.tuple
現已支持[]
。詳見(jiàn) PEP 585 與 GenericAlias 類(lèi)型。
- typing.Union?
Union type;
Union[X, Y]
is equivalent toX | Y
and means either X or Y.To define a union, use e.g.
Union[int, str]
or the shorthandint | str
. Using that shorthand is recommended. Details:參數必須是某種類(lèi)型,且至少有一個(gè)。
聯(lián)合類(lèi)型之聯(lián)合類(lèi)型會(huì )被展平,例如:
Union[Union[int, str], float] == Union[int, str, float]
單參數之聯(lián)合類(lèi)型就是該參數自身,例如:
Union[int] == int # The constructor actually returns int
冗余的參數會(huì )被跳過(guò),例如:
Union[int, str, int] == Union[int, str] == int | str
比較聯(lián)合類(lèi)型,不涉及參數順序,例如:
Union[int, str] == Union[str, int]
You cannot subclass or instantiate a
Union
.不支持
Union[X][Y]
這種寫(xiě)法。
在 3.7 版更改: 在運行時(shí),不要移除聯(lián)合類(lèi)型中的顯式子類(lèi)。
在 3.10 版更改: 聯(lián)合類(lèi)型現在可以寫(xiě)成
X | Y
。 參見(jiàn) 聯(lián)合類(lèi)型表達式。
- typing.Optional?
可選類(lèi)型。
Optional[X]
is equivalent toX | None
(orUnion[X, None]
).注意,可選類(lèi)型與含默認值的可選參數不同。含默認值的可選參數不需要在類(lèi)型注解上添加
Optional
限定符,因為它僅是可選的。例如:def foo(arg: int = 0) -> None: ...
另一方面,顯式應用
None
值時(shí),不管該參數是否可選,Optional
都適用。例如:def foo(arg: Optional[int] = None) -> None: ...
在 3.10 版更改: Optional can now be written as
X | None
. See union type expressions.
- typing.Callable?
可調類(lèi)型;
Callable[[int], str]
是把(int)轉為 str 的函數。下標句法必須與參數列表和返回類(lèi)型這兩個(gè)值一起使用。參數列表只能是類(lèi)型列表或省略號;返回類(lèi)型只能是單一類(lèi)型。
沒(méi)有說(shuō)明可選參數或關(guān)鍵字參數的句法;這類(lèi)函數類(lèi)型很少用作回調類(lèi)型。
Callable[..., ReturnType]
(省略號字面量)可用于為接受任意數量參數,并返回ReturnType
的可調對象提供類(lèi)型提示。純Callable
等價(jià)于Callable[..., Any]
,進(jìn)而等價(jià)于collections.abc.Callable
。以其他可調用對象為參數的可調用對象可以使用
ParamSpec
來(lái)表明其參數類(lèi)型是相互依賴(lài)的。此外,如果該可調用對象增加或刪除了其他可調用對象的參數,可以使用Concatenate
操作符。 它們分別采取``Callable[ParamSpecVariable, ReturnType]`` 和Callable[Concatenate[Arg1Type, Arg2Type, ..., ParamSpecVariable], ReturnType]
的形式。3.9 版后已移除:
collections.abc.Callable
現已支持[]
。 詳見(jiàn) PEP 585 與 GenericAlias 類(lèi)型。在 3.10 版更改:
Callable
現在支持ParamSpec
和Concatenate
。 更多信息見(jiàn) PEP 612。參見(jiàn)
ParamSpec
和Concatenate
的文檔提供了使用Callable
的例子。
- typing.Concatenate?
Used with
Callable
andParamSpec
to type annotate a higher order callable which adds, removes, or transforms parameters of another callable. Usage is in the formConcatenate[Arg1Type, Arg2Type, ..., ParamSpecVariable]
.Concatenate
is currently only valid when used as the first argument to aCallable
. The last parameter toConcatenate
must be aParamSpec
or ellipsis (...
).例如,為了注釋一個(gè)裝飾器
with_lock
,它為被裝飾的函數提供了threading.Lock
,Concatenate
可以用來(lái)表示with_lock
期望一個(gè)可調用對象,該對象接收一個(gè)Lock
作為第一個(gè)參數,并返回一個(gè)具有不同類(lèi)型簽名的可調用對象。 在這種情況下,ParamSpec
表示返回的可調用對象的參數類(lèi)型取決于被傳入的可調用程序的參數類(lèi)型:from collections.abc import Callable from threading import Lock from typing import Concatenate, ParamSpec, TypeVar P = ParamSpec('P') R = TypeVar('R') # Use this lock to ensure that only one thread is executing a function # at any time. my_lock = Lock() def with_lock(f: Callable[Concatenate[Lock, P], R]) -> Callable[P, R]: '''A type-safe decorator which provides a lock.''' def inner(*args: P.args, **kwargs: P.kwargs) -> R: # Provide the lock as the first argument. return f(my_lock, *args, **kwargs) return inner @with_lock def sum_threadsafe(lock: Lock, numbers: list[float]) -> float: '''Add a list of numbers together in a thread-safe manner.''' with lock: return sum(numbers) # We don't need to pass in the lock ourselves thanks to the decorator. sum_threadsafe([1.1, 2.2, 3.3])
3.10 新版功能.
- class typing.Type(Generic[CT_co])?
用
C
注解的變量可以接受類(lèi)型C
的值。反之,用Type[C]
注解的變量可以接受類(lèi)自身的值 — 準確地說(shuō),是接受C
的 類(lèi)對象,例如:a = 3 # Has type 'int' b = int # Has type 'Type[int]' c = type(a) # Also has type 'Type[int]'
注意,
Type[C]
為協(xié)變量: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]
為協(xié)變量的意思是指,C
的所有子類(lèi)都應使用與C
相同的構造器簽名及類(lèi)方法簽名。類(lèi)型檢查器應標記違反此項規定的內容,但也應允許符合指定基類(lèi)構造器調用的子類(lèi)進(jìn)行構造器調用。PEP 484 修訂版將來(lái)可能會(huì )調整類(lèi)型檢查器對這種特例的處理方式。Type
合法的參數僅有類(lèi)、Any
、類(lèi)型變量 以及上述類(lèi)型的聯(lián)合類(lèi)型。例如:def new_non_team_user(user_class: Type[BasicUser | ProUser]): ...
Type[Any]
等價(jià)于Type
,進(jìn)而等價(jià)于 Python 元類(lèi)架構的根基,type
。3.5.2 新版功能.
3.9 版后已移除:
builtins.type
現已支持[]
。詳見(jiàn) PEP 585 與 GenericAlias 類(lèi)型。
- typing.Literal?
表示類(lèi)型檢查器對應變量或函數參數的值等價(jià)于給定字面量(或多個(gè)字面量之一)的類(lèi)型。例如:
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[...]
不能創(chuàng )建子類(lèi)。在運行時(shí),任意值均可作為Literal[...]
的類(lèi)型參數,但類(lèi)型檢查器可以對此加以限制。字面量類(lèi)型詳見(jiàn) PEP 586 。3.8 新版功能.
- typing.ClassVar?
標記類(lèi)變量的特殊類(lèi)型構造器。
如 PEP 526 所述,打包在 ClassVar 內的變量注解是指,給定屬性應當用作類(lèi)變量,而不應設置在類(lèi)實(shí)例上。用法如下:
class Starship: stats: ClassVar[dict[str, int]] = {} # class variable damage: int = 10 # instance variable
ClassVar
僅接受類(lèi)型,也不能使用下標。ClassVar
本身不是類(lèi),不應用于isinstance()
或issubclass()
。ClassVar
不改變 Python 運行時(shí)行為,但可以用于第三方類(lèi)型檢查器。例如,類(lèi)型檢查器會(huì )認為以下代碼有錯:enterprise_d = Starship(3000) enterprise_d.stats = {} # Error, setting class variable on instance Starship.stats = {} # This is OK
3.5.3 新版功能.
- typing.Final?
告知類(lèi)型檢查器某名稱(chēng)不能再次賦值或在子類(lèi)中重寫(xiě)的特殊類(lèi)型構造器。例如:
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
這些屬性沒(méi)有運行時(shí)檢查。詳見(jiàn) PEP 591。
3.8 新版功能.
- typing.Annotated?
A type, introduced in PEP 593 (
Flexible function and variable annotations
), to decorate existing types with context-specific metadata (possibly multiple pieces of it, asAnnotated
is variadic). Specifically, a typeT
can be annotated with metadatax
via the typehintAnnotated[T, x]
. This metadata can be used for either static analysis or at runtime. If a library (or tool) encounters a typehintAnnotated[T, x]
and has no special logic for metadatax
, it should ignore it and simply treat the type asT
. Unlike theno_type_check
functionality that currently exists in thetyping
module which completely disables typechecking annotations on a function or a class, theAnnotated
type allows for both static typechecking ofT
(which can safely ignorex
) together with runtime access tox
within a specific application.畢竟,如何解釋注解(如有)由處理
Annotated
類(lèi)型的工具/庫負責。工具/庫處理Annotated
類(lèi)型時(shí),掃描所有注解以確定是否需要進(jìn)行處理(例如,使用isinstance()
)。工具/庫不支持注解,或遇到未知注解時(shí),應忽略注解,并把注解類(lèi)型當作底層類(lèi)型。
是否允許客戶(hù)端在一個(gè)類(lèi)型上使用多個(gè)注解,以及如何合并這些注解,由處理注解的工具決定。
Annotated
類(lèi)型支持把多個(gè)相同(或不同)的單個(gè)(或多個(gè))類(lèi)型注解置于任意節點(diǎn)。因此,使用這些注解的工具/庫要負責處理潛在的重復項。例如,執行值范圍分析時(shí),應允許以下操作:T1 = Annotated[int, ValueRange(-10, 5)] T2 = Annotated[T1, ValueRange(-20, 3)]
傳遞
include_extras=True
至get_type_hints()
,即可在運行時(shí)訪(fǎng)問(wèn)額外的注解。語(yǔ)義詳情:
Annotated
的第一個(gè)參數必須是有效類(lèi)型。支持多個(gè)類(lèi)型標注(
Annotated
支持可變參數):Annotated[int, ValueRange(3, 10), ctype("char")]
調用
Annotated
至少要有兩個(gè)參數(Annotated[int]
是無(wú)效的)注解的順序會(huì )被保留,且影響等價(jià)檢查:
Annotated[int, ValueRange(3, 10), ctype("char")] != Annotated[ int, ctype("char"), ValueRange(3, 10) ]
嵌套
Annotated
類(lèi)型會(huì )被展平,元數據從最內層注解依序展開(kāi):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 新版功能.
- typing.TypeGuard?
用于注釋用戶(hù)定義的類(lèi)型保護函數的返回類(lèi)型的特殊類(lèi)型化形式。
TypeGuard
只接受一個(gè)單一的類(lèi)型參數。 在運行時(shí),以這種方式標記的函數應該返回一個(gè)布爾值。PX旨在使 類(lèi)型縮小 受益--這是靜態(tài)類(lèi)型檢查器用來(lái)確定程序代碼流中表達式的更精確類(lèi)型的一種技術(shù)。通常,類(lèi)型縮小是通過(guò)分析條件性代碼流并將縮小的結果應用于一個(gè)代碼塊來(lái)完成的。 這里的條件表達式有時(shí)被稱(chēng)為 "類(lèi)型保護":
def is_str(val: str | float): # "isinstance" type guard if isinstance(val, str): # Type of ``val`` is narrowed to ``str`` ... else: # Else, type of ``val`` is narrowed to ``float``. ...
有時(shí),使用一個(gè)用戶(hù)定義的布爾函數作為類(lèi)型保護會(huì )很方便。 這樣的函數應該使用
TypeGuard[...]
作為其返回類(lèi)型,以提醒靜態(tài)類(lèi)型檢查器注意這一意圖。對于一個(gè)給定的函數,使用
-> TypeGuard
告訴靜態(tài)類(lèi)型檢查器:返回值是一個(gè)布爾值。
如果返回值是
True
,其參數的類(lèi)型是TypeGuard
里面的類(lèi)型。
例如:
def is_str_list(val: list[object]) -> TypeGuard[list[str]]: '''Determines whether all objects in the list are strings''' return all(isinstance(x, str) for x in val) def func1(val: list[object]): if is_str_list(val): # Type of ``val`` is narrowed to ``list[str]``. print(" ".join(val)) else: # Type of ``val`` remains as ``list[object]``. print("Not a list of strings!")
如果
is_str_list
是一個(gè)類(lèi)或實(shí)例方法,那么TypeGuard
中的類(lèi)型映射到cls
或self
之后的第二個(gè)參數的類(lèi)型。簡(jiǎn)而言之,
def foo(arg: TypeA) -> TypeGuard[TypeB]: ...
形式的意思是:如果foo(arg)
返回True
,那么arg
將把TypeA
縮小為TypeB
。備注
TypeB
need not be a narrower form ofTypeA
-- it can even be a wider form. The main reason is to allow for things like narrowinglist[object]
tolist[str]
even though the latter is not a subtype of the former, sincelist
is invariant. The responsibility of writing type-safe type guards is left to the user.TypeGuard
also works with type variables. For more information, see PEP 647 (User-Defined Type Guards).3.10 新版功能.
構建泛型類(lèi)型?
以下內容是創(chuàng )建泛型類(lèi)型的基石,但不在注解內使用。
- class typing.Generic?
用于泛型類(lèi)型的抽象基類(lèi)。
泛型類(lèi)型一般通過(guò)繼承含一個(gè)或多個(gè)類(lèi)型變量的類(lèi)實(shí)例進(jìn)行聲明。例如,泛型映射類(lèi)型定義如下:
class Mapping(Generic[KT, VT]): def __getitem__(self, key: KT) -> VT: ... # Etc.
該類(lèi)的用法如下:
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?
類(lèi)型變量。
用法:
T = TypeVar('T') # Can be anything S = TypeVar('S', bound=str) # Can be any subtype of str A = TypeVar('A', str, bytes) # Must be exactly str or bytes
類(lèi)型變量主要是為靜態(tài)類(lèi)型檢查器提供支持,用于泛型類(lèi)型與泛型函數定義的參數。有關(guān)泛型類(lèi)型,詳見(jiàn)
Generic
。泛型函數的寫(xiě)法如下:def repeat(x: T, n: int) -> Sequence[T]: """Return a list containing n references to x.""" return [x]*n def print_capitalized(x: S) -> S: """Print x capitalized, and return x.""" print(x.capitalize()) return x def concatenate(x: A, y: A) -> A: """Add two strings or bytes objects together.""" return x + y
Note that type variables can be bound, constrained, or neither, but cannot be both bound and constrained.
Bound type variables and constrained type variables have different semantics in several important ways. Using a bound type variable means that the
TypeVar
will be solved using the most specific type possible:x = print_capitalized('a string') reveal_type(x) # revealed type is str class StringSubclass(str): pass y = print_capitalized(StringSubclass('another string')) reveal_type(y) # revealed type is StringSubclass z = print_capitalized(45) # error: int is not a subtype of str
Type variables can be bound to concrete types, abstract types (ABCs or protocols), and even unions of types:
U = TypeVar('U', bound=str|bytes) # Can be any subtype of the union str|bytes V = TypeVar('V', bound=SupportsAbs) # Can be anything with an __abs__ method
Using a constrained type variable, however, means that the
TypeVar
can only ever be solved as being exactly one of the constraints given:a = concatenate('one', 'two') reveal_type(a) # revealed type is str b = concatenate(StringSubclass('one'), StringSubclass('two')) reveal_type(b) # revealed type is str, despite StringSubclass being passed in c = concatenate('one', b'two') # error: type variable 'A' can be either str or bytes in a function call, but not both
在運行時(shí),
isinstance(x, T)
會(huì )觸發(fā)TypeError
異常。一般而言,isinstance()
和issubclass()
不應與類(lèi)型搭配使用。Type variables may be marked covariant or contravariant by passing
covariant=True
orcontravariant=True
. See PEP 484 for more details. By default, type variables are invariant.
- class typing.TypeVarTuple?
Type variable tuple. A specialized form of
type variable
that enables variadic generics.A normal type variable enables parameterization with a single type. A type variable tuple, in contrast, allows parameterization with an arbitrary number of types by acting like an arbitrary number of type variables wrapped in a tuple. For example:
T = TypeVar('T') Ts = TypeVarTuple('Ts') def remove_first_element(tup: tuple[T, *Ts]) -> tuple[*Ts]: return tup[1:] # T is bound to int, Ts is bound to () # Return value is (), which has type tuple[()] remove_first_element(tup=(1,)) # T is bound to int, Ts is bound to (str,) # Return value is ('spam',), which has type tuple[str] remove_first_element(tup=(1, 'spam')) # T is bound to int, Ts is bound to (str, float) # Return value is ('spam', 3.0), which has type tuple[str, float] remove_first_element(tup=(1, 'spam', 3.0))
Note the use of the unpacking operator
*
intuple[T, *Ts]
. Conceptually, you can think ofTs
as a tuple of type variables(T1, T2, ...)
.tuple[T, *Ts]
would then becometuple[T, *(T1, T2, ...)]
, which is equivalent totuple[T, T1, T2, ...]
. (Note that in older versions of Python, you might see this written usingUnpack
instead, asUnpack[Ts]
.)Type variable tuples must always be unpacked. This helps distinguish type variable types from normal type variables:
x: Ts # Not valid x: tuple[Ts] # Not valid x: tuple[*Ts] # The correct way to to do it
Type variable tuples can be used in the same contexts as normal type variables. For example, in class definitions, arguments, and return types:
Shape = TypeVarTuple('Shape') class Array(Generic[*Shape]): def __getitem__(self, key: tuple[*Shape]) -> float: ... def __abs__(self) -> Array[*Shape]: ... def get_shape(self) -> tuple[*Shape]: ...
Type variable tuples can be happily combined with normal type variables:
DType = TypeVar('DType') class Array(Generic[DType, *Shape]): # This is fine pass class Array2(Generic[*Shape, DType]): # This would also be fine pass float_array_1d: Array[float, Height] = Array() # Totally fine int_array_2d: Array[int, Height, Width] = Array() # Yup, fine too
However, note that at most one type variable tuple may appear in a single list of type arguments or type parameters:
x: tuple[*Ts, *Ts] # Not valid class Array(Generic[*Shape, *Shape]): # Not valid pass
Finally, an unpacked type variable tuple can be used as the type annotation of
*args
:def call_soon( callback: Callable[[*Ts], None], *args: *Ts ) -> None: ... callback(*args)
In contrast to non-unpacked annotations of
*args
- e.g.*args: int
, which would specify that all arguments areint
-*args: *Ts
enables reference to the types of the individual arguments in*args
. Here, this allows us to ensure the types of the*args
passed tocall_soon
match the types of the (positional) arguments ofcallback
.For more details on type variable tuples, see PEP 646.
3.11 新版功能.
- typing.Unpack?
A typing operator that conceptually marks an object as having been unpacked. For example, using the unpack operator
*
on atype variable tuple
is equivalent to usingUnpack
to mark the type variable tuple as having been unpacked:Ts = TypeVarTuple('Ts') tup: tuple[*Ts] # Effectively does: tup: tuple[Unpack[Ts]]
In fact,
Unpack
can be used interchangeably with*
in the context of types. You might seeUnpack
being used explicitly in older versions of Python, where*
couldn't be used in certain places:# In older versions of Python, TypeVarTuple and Unpack # are located in the `typing_extensions` backports package. from typing_extensions import TypeVarTuple, Unpack Ts = TypeVarTuple('Ts') tup: tuple[*Ts] # Syntax error on Python <= 3.10! tup: tuple[Unpack[Ts]] # Semantically equivalent, and backwards-compatible
3.11 新版功能.
- class typing.ParamSpec(name, *, bound=None, covariant=False, contravariant=False)?
參數規范變量。
類(lèi)型變量
的一個(gè)專(zhuān)門(mén)版本。用法:
P = ParamSpec('P')
參數規范變量的存在主要是為了使靜態(tài)類(lèi)型檢查器受益。 它們被用來(lái)將一個(gè)可調用對象的參數類(lèi)型轉發(fā)給另一個(gè)可調用對象的參數類(lèi)型——這種模式通常出現在高階函數和裝飾器中。 它們只有在
Concatenate
中使用時(shí)才有效,或者作為Callable
的第一個(gè)參數,或者作為用戶(hù)定義的泛型的參數。 參見(jiàn)Generic
以了解更多關(guān)于泛型的信息。例如,為了給一個(gè)函數添加基本的日志記錄,我們可以創(chuàng )建一個(gè)裝飾器
add_logging
來(lái)記錄函數調用。 參數規范變量告訴類(lèi)型檢查器,傳入裝飾器的可調用對象和由其返回的新可調用對象有相互依賴(lài)的類(lèi)型參數:from collections.abc import Callable from typing import TypeVar, ParamSpec import logging T = TypeVar('T') P = ParamSpec('P') def add_logging(f: Callable[P, T]) -> Callable[P, T]: '''A type-safe decorator to add logging to a function.''' def inner(*args: P.args, **kwargs: P.kwargs) -> T: logging.info(f'{f.__name__} was called') return f(*args, **kwargs) return inner @add_logging def add_two(x: float, y: float) -> float: '''Add two numbers together.''' return x + y
如果沒(méi)有
ParamSpec
,以前注釋這個(gè)的最簡(jiǎn)單的方法是使用一個(gè)TypeVar
與綁定Callable[..., Any]
。類(lèi)型檢查器不能對
inner
函數進(jìn)行類(lèi)型檢查,因為*args
和**kwargs
的類(lèi)型必須是Any
。cast()
在返回inner
函數時(shí),可能需要在add_logging
裝飾器的主體中進(jìn)行,或者必須告訴靜態(tài)類(lèi)型檢查器忽略return inner
。
- args?
- kwargs?
由于
ParamSpec
同時(shí)捕獲了位置參數和關(guān)鍵字參數,P.args
和P.kwargs
可以用來(lái)將ParamSpec
分割成其組成部分。P.args
代表給定調用中的位置參數的元組,只能用于注釋*args
。P.kwargs
代表給定調用中的關(guān)鍵字參數到其值的映射,只能用于注釋**kwargs
。在運行時(shí),P.args
和P.kwargs
分別是ParamSpecArgs
和ParamSpecKwargs
的實(shí)例。
用
covariant=True
或contravariant=True
創(chuàng )建的參數規范變量可以用來(lái)聲明協(xié)變或禁變的通用類(lèi)型。 參數bound
也被接受,類(lèi)似于TypeVar
。 然而這些關(guān)鍵字的實(shí)際語(yǔ)義還有待決定。3.10 新版功能.
備注
只有在全局范圍內定義的參數規范變量可以被 pickle。
參見(jiàn)
PEP 612 -- 參數規范變量(引入
ParamSpec
和Concatenate
的 PEP)。
- typing.ParamSpecArgs?
- typing.ParamSpecKwargs?
ParamSpec`的參數和關(guān)鍵字參數屬性。``ParamSpec`
的P.args
屬性是ParamSpecArgs
的一個(gè)實(shí)例,P.kwargs
是ParamSpecKwargs
的一個(gè)實(shí)例。 它們的目的是用于運行時(shí)內部檢查的,對靜態(tài)類(lèi)型檢查器沒(méi)有特殊意義。在這些對象中的任何一個(gè)上調用
get_origin()
,都會(huì )返回原始的ParamSpec
:P = ParamSpec("P") get_origin(P.args) # returns P get_origin(P.kwargs) # returns P
3.10 新版功能.
- typing.AnyStr?
AnyStr
is aconstrained type variable
defined asAnyStr = TypeVar('AnyStr', str, bytes)
.這里指的是,它可以接受任意同類(lèi)字符串,但不支持混用不同類(lèi)別的字符串。例如:
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 類(lèi)的基類(lèi)。Protocol 類(lèi)的定義如下:
class Proto(Protocol): def meth(self) -> int: ...
這些類(lèi)主要與靜態(tài)類(lèi)型檢查器搭配使用,用來(lái)識別結構子類(lèi)型(靜態(tài)鴨子類(lèi)型),例如:
class C: def meth(self) -> int: return 0 def func(x: Proto) -> int: return x.meth() func(C()) # Passes static type check
詳見(jiàn) PEP 544。Protocol 類(lèi)用
runtime_checkable()
(見(jiàn)下文)裝飾,忽略類(lèi)型簽名,僅檢查給定屬性是否存在,充當簡(jiǎn)要的運行時(shí)協(xié)議。Protocol 類(lèi)可以是泛型,例如:
class GenProto(Protocol[T]): def meth(self) -> T: ...
3.8 新版功能.
- @typing.runtime_checkable?
用于把 Protocol 類(lèi)標記為運行時(shí)協(xié)議。
該協(xié)議可以與
isinstance()
和issubclass()
一起使用。應用于非協(xié)議的類(lèi)時(shí),會(huì )觸發(fā)TypeError
。該指令支持簡(jiǎn)易結構檢查,與collections.abc
的Iterable
非常類(lèi)似,只擅長(cháng)做一件事。 例如:@runtime_checkable class Closable(Protocol): def close(self): ... assert isinstance(open('/some/file'), Closable)
備注
runtime_checkable()
將只檢查所需方法的存在,而不是其類(lèi)型簽名。 例如,ssl.SSLObject
是一個(gè)類(lèi),因此它通過(guò)了issubclass()
對Callable
的檢查。 然而,ssl.SSLObject.__init__()
方法的存在只是為了引發(fā)一個(gè)TypeError
的更多信息,因此使它無(wú)法調用(實(shí)例化)ssl.SSLObject
。3.8 新版功能.
其他特殊指令?
這些特殊指令是聲明類(lèi)型的基石,但不在注解內使用。
- class typing.NamedTuple?
collections.namedtuple()
的類(lèi)型版本。用法:
class Employee(NamedTuple): name: str id: int
這相當于:
Employee = collections.namedtuple('Employee', ['name', 'id'])
為字段提供默認值,要在類(lèi)體內賦值:
class Employee(NamedTuple): name: str id: int = 3 employee = Employee('Guido') assert employee.id == 3
帶默認值的字段必須在不帶默認值的字段后面。
The resulting class has an extra attribute
__annotations__
giving a dict that maps the field names to the field types. (The field names are in the_fields
attribute and the default values are in the_field_defaults
attribute, both of which are part of thenamedtuple()
API.)NamedTuple
子類(lèi)也支持文檔字符串與方法:class Employee(NamedTuple): """Represents an employee.""" name: str id: int = 3 def __repr__(self) -> str: return f'<Employee {self.name}, id={self.id}>'
NamedTuple
subclasses can be generic:class Group(NamedTuple, Generic[T]): key: T group: list[T]
反向兼容用法:
Employee = NamedTuple('Employee', [('name', str), ('id', int)])
在 3.6 版更改: 添加了對 PEP 526 中變量注解句法的支持。
在 3.6.1 版更改: 添加了對默認值、方法、文檔字符串的支持。
在 3.8 版更改:
_field_types
和__annotations__
屬性現已使用常規字典,不再使用OrderedDict
實(shí)例。在 3.9 版更改: 移除了
_field_types
屬性, 改用具有相同信息,但更標準的__annotations__
屬性。在 3.11 版更改: Added support for generic namedtuples.
- class typing.NewType(name, tp)?
一個(gè)輔助類(lèi),用于向類(lèi)型檢查器指示一個(gè)不同的類(lèi)型,見(jiàn) NewType。在運行時(shí),它返回一個(gè)對象,在調用時(shí)返回其參數。用法:
UserId = NewType('UserId', int) first_user = UserId(1)
3.5.2 新版功能.
在 3.10 版更改:
NewType
現在是一個(gè)類(lèi)而不是函數。
- class typing.TypedDict(dict)?
把類(lèi)型提示添加至字典的特殊構造器。在運行時(shí),它是純
dict
。TypedDict
聲明一個(gè)字典類(lèi)型,該類(lèi)型預期所有實(shí)例都具有一組鍵集,其中,每個(gè)鍵都與對應類(lèi)型的值關(guān)聯(lián)。運行時(shí)不檢查此預期,而是由類(lèi)型檢查器強制執行。用法如下: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')
To allow using this feature with older versions of Python that do not support PEP 526,
TypedDict
supports two additional equivalent syntactic forms:Using a literal
dict
as the second argument:Point2D = TypedDict('Point2D', {'x': int, 'y': int, 'label': str})
Using keyword arguments:
Point2D = TypedDict('Point2D', x=int, y=int, label=str)
Deprecated since version 3.11, will be removed in version 3.13: The keyword-argument syntax is deprecated in 3.11 and will be removed in 3.13. It may also be unsupported by static type checkers.
The functional syntax should also be used when any of the keys are not valid identifiers, for example because they are keywords or contain hyphens. Example:
# raises SyntaxError class Point2D(TypedDict): in: int # 'in' is a keyword x-y: int # name with hyphens # OK, functional syntax Point2D = TypedDict('Point2D', {'in': int, 'x-y': int})
默認情況下,所有的鍵都必須出現在一個(gè)
TypedDict
中。 可以通過(guò)指定總數來(lái)重寫(xiě)這一點(diǎn)。用法:class Point2D(TypedDict, total=False): x: int y: int # Alternative syntax Point2D = TypedDict('Point2D', {'x': int, 'y': int}, total=False)
這意味著(zhù)一個(gè)
Point2D
TypedDict
可以省略任何一個(gè)鍵。 類(lèi)型檢查器只需要支持一個(gè)字面的False
或True
作為total
參數的值。True
是默認的,它使類(lèi)主體中定義的所有項目都是必需的。It is possible for a
TypedDict
type to inherit from one or more otherTypedDict
types using the class-based syntax. Usage:class Point3D(Point2D): z: int
Point3D
has three items:x
,y
andz
. It is equivalent to this definition:class Point3D(TypedDict): x: int y: int z: int
A
TypedDict
cannot inherit from a non-TypedDict
class, except forGeneric
. For example:class X(TypedDict): x: int class Y(TypedDict): y: int class Z(object): pass # A non-TypedDict class class XY(X, Y): pass # OK class XZ(X, Z): pass # raises TypeError T = TypeVar('T') class XT(X, Generic[T]): pass # raises TypeError
A
TypedDict
can be generic:class Group(TypedDict, Generic[T]): key: T group: list[T]
A
TypedDict
can be introspected via annotations dicts (see 對象注解屬性的最佳實(shí)踐 for more information on annotations best practices),__total__
,__required_keys__
, and__optional_keys__
.- __total__?
Point2D.__total__
gives the value of thetotal
argument. Example:>>> from typing import TypedDict >>> class Point2D(TypedDict): pass >>> Point2D.__total__ True >>> class Point2D(TypedDict, total=False): pass >>> Point2D.__total__ False >>> class Point3D(Point2D): pass >>> Point3D.__total__ True
- __required_keys__?
- __optional_keys__?
Point2D.__required_keys__
andPoint2D.__optional_keys__
returnfrozenset
objects containing required and non-required keys, respectively. Currently the only way to declare both required and non-required keys in the sameTypedDict
is mixed inheritance, declaring aTypedDict
with one value for thetotal
argument and then inheriting it from anotherTypedDict
with a different value fortotal
. Usage:>>> class Point2D(TypedDict, total=False): ... x: int ... y: int ... >>> class Point3D(Point2D): ... z: int ... >>> Point3D.__required_keys__ == frozenset({'z'}) True >>> Point3D.__optional_keys__ == frozenset({'x', 'y'}) True
更多示例與
TypedDict
的詳細規則,詳見(jiàn) PEP 589。3.8 新版功能.
在 3.11 版更改: Added support for generic
TypedDict
s.
泛型具象容器?
對應的內置類(lèi)型?
- class typing.Dict(dict, MutableMapping[KT, VT])?
dict
的泛型版本。適用于注解返回類(lèi)型。注解參數時(shí),最好使用Mapping
等抽象容器類(lèi)型。該類(lèi)型用法如下:
def count_words(text: str) -> Dict[str, int]: ...
3.9 版后已移除:
builtins.dict
現已支持[]
。詳見(jiàn) PEP 585 和 GenericAlias 類(lèi)型。
- class typing.List(list, MutableSequence[T])?
list
的泛型版本。適用于注解返回類(lèi)型。注解參數時(shí),最好使用Sequence
或Iterable
等抽象容器類(lèi)型。該類(lèi)型用法如下:
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
現已支持[]
。詳見(jiàn) PEP 585 與 GenericAlias 類(lèi)型。
- class typing.Set(set, MutableSet[T])?
builtins.set
的泛型版本。適用于注解返回類(lèi)型。注解參數時(shí),最好使用AbstractSet
等抽象容器類(lèi)型。3.9 版后已移除:
builtins.set
現已支持[]
。詳見(jiàn) PEP 585 和 GenericAlias 類(lèi)型。
- class typing.FrozenSet(frozenset, AbstractSet[T_co])?
builtins.frozenset
的泛型版本。3.9 版后已移除:
builtins.frozenset
現已支持[]
。詳見(jiàn) PEP 585 和 GenericAlias 類(lèi)型。
備注
Tuple
是一種特殊形式。
collections
對應類(lèi)型?
- class typing.DefaultDict(collections.defaultdict, MutableMapping[KT, VT])?
collections.defaultdict
的泛型版本。3.5.2 新版功能.
3.9 版后已移除:
collections.defaultdict
現已支持[]
。詳見(jiàn) PEP 585 與 GenericAlias 類(lèi)型。
- class typing.OrderedDict(collections.OrderedDict, MutableMapping[KT, VT])?
collections.OrderedDict
的泛型版本。3.7.2 新版功能.
3.9 版后已移除:
collections.OrderedDict
現已支持[]
。詳見(jiàn) PEP 585 與 GenericAlias 類(lèi)型。
- class typing.ChainMap(collections.ChainMap, MutableMapping[KT, VT])?
collections.ChainMap
的泛型版本。3.5.4 新版功能.
3.6.1 新版功能.
3.9 版后已移除:
collections.ChainMap
現已支持[]
。詳見(jiàn) PEP 585 和 GenericAlias 類(lèi)型。
- class typing.Counter(collections.Counter, Dict[T, int])?
collections.Counter
的泛型版本。3.5.4 新版功能.
3.6.1 新版功能.
3.9 版后已移除:
collections.Counter
現已支持[]
。詳見(jiàn) PEP 585 和 GenericAlias 類(lèi)型。
- class typing.Deque(deque, MutableSequence[T])?
collections.deque
的泛型版本。3.5.4 新版功能.
3.6.1 新版功能.
3.9 版后已移除:
collections.deque
現已支持[]
。詳見(jiàn) PEP 585 和 GenericAlias 類(lèi)型。
其他具象類(lèi)型?
- class typing.IO?
- class typing.TextIO?
- class typing.BinaryIO?
泛型類(lèi)型
IO[AnyStr]
及其子類(lèi)TextIO(IO[str])
與BinaryIO(IO[bytes])
表示 I/O 流的類(lèi)型,例如open()
所返回的對象。Deprecated since version 3.8, removed in version 3.12: The
typing.io
namespace is deprecated and will be removed. These types should be directly imported fromtyping
instead.
- class typing.Pattern?
- class typing.Match?
這些類(lèi)型對應的是從
re.compile()
和re.match()
返回的類(lèi)型。 這些類(lèi)型(及相應的函數)是AnyStr
中的泛型并可通過(guò)編寫(xiě)Pattern[str]
,Pattern[bytes]
,Match[str]
或Match[bytes]
來(lái)具體指定。Deprecated since version 3.8, removed in version 3.12: The
typing.re
namespace is deprecated and will be removed. These types should be directly imported fromtyping
instead.3.9 版后已移除:
re
模塊中的Pattern
與Match
類(lèi)現已支持[]
。詳見(jiàn) PEP 585 與 GenericAlias 類(lèi)型。
- class typing.Text?
Text
是str
的別名。提供了對 Python 2 代碼的向下兼容:Python 2 中,Text
是unicode
的別名。使用
Text
時(shí),值中必須包含 unicode 字符串,以兼容 Python 2 和 Python 3:def add_unicode_checkmark(text: Text) -> Text: return text + u' \u2713'
3.5.2 新版功能.
3.11 版后已移除: Python 2 is no longer supported, and most type checkers also no longer support type checking Python 2 code. Removal of the alias is not currently planned, but users are encouraged to use
str
instead ofText
wherever possible.
抽象基類(lèi)?
collections.abc
對應的容器?
- class typing.AbstractSet(Sized, Collection[T_co])?
collections.abc.Set
的泛型版本。3.9 版后已移除:
collections.abc.Set
現已支持[]
。詳見(jiàn) PEP 585 與 GenericAlias 類(lèi)型。
- class typing.ByteString(Sequence[int])?
collections.abc.ByteString
的泛型版本。該類(lèi)型代表了
bytes
、bytearray
、memoryview
等字節序列類(lèi)型。作為該類(lèi)型的簡(jiǎn)稱(chēng),
bytes
可用于標注上述任意類(lèi)型的參數。3.9 版后已移除:
collections.abc.ByteString
現已支持[]
。詳見(jiàn) PEP 585 與 GenericAlias 類(lèi)型。
- class typing.Collection(Sized, Iterable[T_co], Container[T_co])?
collections.abc.Collection
的泛型版本。3.6.0 新版功能.
3.9 版后已移除:
collections.abc.Collection
現已支持[]
。詳見(jiàn) PEP 585 與 GenericAlias 類(lèi)型。
- class typing.Container(Generic[T_co])?
collections.abc.Container
的泛型版本。3.9 版后已移除:
collections.abc.Container
現已支持[]
。詳見(jiàn) PEP 585 和 GenericAlias 類(lèi)型。
- class typing.ItemsView(MappingView, Generic[KT_co, VT_co])?
collections.abc.ItemsView
的泛型版本。3.9 版后已移除:
collections.abc.ItemsView
現已支持[]
。詳見(jiàn) PEP 585 和 GenericAlias 類(lèi)型。
- class typing.KeysView(MappingView[KT_co], AbstractSet[KT_co])?
collections.abc.KeysView
的泛型版本。3.9 版后已移除:
collections.abc.KeysView
現已支持[]
。詳見(jiàn) PEP 585 和 GenericAlias 類(lèi)型。
- 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
現已支持[]
。詳見(jiàn) PEP 585 和 GenericAlias 類(lèi)型。
- class typing.MappingView(Sized, Iterable[T_co])?
collections.abc.MappingView
的泛型版本。3.9 版后已移除:
collections.abc.MappingView
現已支持[]
。詳見(jiàn) PEP 585 和 GenericAlias 類(lèi)型。
- class typing.MutableMapping(Mapping[KT, VT])?
collections.abc.MutableMapping
的泛型版本。3.9 版后已移除:
collections.abc.MutableMapping
現已支持[]
。詳見(jiàn) PEP 585 和 GenericAlias 類(lèi)型。
- class typing.MutableSequence(Sequence[T])?
collections.abc.MutableSequence
的泛型版本。3.9 版后已移除:
collections.abc.MutableSequence
現已支持[]
。詳見(jiàn) PEP 585 和 GenericAlias 類(lèi)型。
- class typing.MutableSet(AbstractSet[T])?
collections.abc.MutableSet
的泛型版本。3.9 版后已移除:
collections.abc.MutableSet
現已支持[]
。詳見(jiàn) PEP 585 和 GenericAlias 類(lèi)型。
- class typing.Sequence(Reversible[T_co], Collection[T_co])?
collections.abc.Sequence
的泛型版本。3.9 版后已移除:
collections.abc.Sequence
現已支持[]
。詳見(jiàn) PEP 585 和 GenericAlias 類(lèi)型。
- class typing.ValuesView(MappingView[VT_co])?
collections.abc.ValuesView
的泛型版本。3.9 版后已移除:
collections.abc.ValuesView
現已支持[]
。詳見(jiàn) PEP 585 和 GenericAlias 類(lèi)型。
collections.abc
對應的其他類(lèi)型?
- class typing.Iterable(Generic[T_co])?
collections.abc.Iterable
的泛型版本。3.9 版后已移除:
collections.abc.Iterable
現已支持[]
。詳見(jiàn) PEP 585 和 GenericAlias 類(lèi)型。
- class typing.Iterator(Iterable[T_co])?
collections.abc.Iterator
的泛型版本。3.9 版后已移除:
collections.abc.Iterator
現已支持[]
。詳見(jiàn) PEP 585 和 GenericAlias 類(lèi)型。
- class typing.Generator(Iterator[T_co], Generic[T_co, T_contra, V_co])?
生成器可以由泛型類(lèi)型
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
屬于逆變行為,不是協(xié)變行為,也是不變行為。如果生成器只產(chǎn)生值,可將
SendType
與ReturnType
設為None
:def infinite_stream(start: int) -> Generator[int, None, None]: while True: yield start start += 1
此外,還可以把生成器的返回類(lèi)型注解為
Iterable[YieldType]
或Iterator[YieldType]
:def infinite_stream(start: int) -> Iterator[int]: while True: yield start start += 1
3.9 版后已移除:
collections.abc.Generator
現已支持[]
。詳見(jiàn) PEP 585 和 GenericAlias 類(lèi)型。
- class typing.Hashable?
An alias to
collections.abc.Hashable
.
- class typing.Reversible(Iterable[T_co])?
collections.abc.Reversible
的泛型版本。3.9 版后已移除:
collections.abc.Reversible
現已支持[]
。詳見(jiàn) PEP 585 和 GenericAlias 類(lèi)型。
- class typing.Sized?
An alias to
collections.abc.Sized
.
異步編程?
- class typing.Coroutine(Awaitable[V_co], Generic[T_co, T_contra, V_co])?
collections.abc.Coroutine
的泛型版本。類(lèi)型變量的差異和順序與Generator
的內容相對應,例如:from collections.abc import Coroutine c: Coroutine[list[str], str, int] # Some coroutine defined elsewhere x = c.send('hi') # Inferred type of 'x' is list[str] async def bar() -> None: y = await c # Inferred type of 'y' is int
3.5.3 新版功能.
3.9 版后已移除:
collections.abc.Coroutine
現已支持[]
。詳見(jiàn) PEP 585 和 GenericAlias 類(lèi)型。
- class typing.AsyncGenerator(AsyncIterator[T_co], Generic[T_co, T_contra])?
異步生成器可由泛型類(lèi)型
AsyncGenerator[YieldType, SendType]
注解。例如:async def echo_round() -> AsyncGenerator[int, float]: sent = yield 0 while sent >= 0.0: rounded = await round(sent) sent = yield rounded
與常規生成器不同,異步生成器不能返回值,因此沒(méi)有
ReturnType
類(lèi)型參數。 與Generator
類(lèi)似,SendType
也屬于逆變行為。如果生成器只產(chǎn)生值,可將
SendType
設置為None
:async def infinite_stream(start: int) -> AsyncGenerator[int, None]: while True: yield start start = await increment(start)
此外,可用
AsyncIterable[YieldType]
或AsyncIterator[YieldType]
注解生成器的返回類(lèi)型:async def infinite_stream(start: int) -> AsyncIterator[int]: while True: yield start start = await increment(start)
3.6.1 新版功能.
3.9 版后已移除:
collections.abc.AsyncGenerator
現已支持[]
。詳見(jiàn) PEP 585 和 GenericAlias 類(lèi)型。
- class typing.AsyncIterable(Generic[T_co])?
collections.abc.AsyncIterable
的泛型版本。3.5.2 新版功能.
3.9 版后已移除:
collections.abc.AsyncIterable
現已支持[]
。詳見(jiàn) PEP 585 和 GenericAlias 類(lèi)型。
- class typing.AsyncIterator(AsyncIterable[T_co])?
collections.abc.AsyncIterator
的泛型版本。3.5.2 新版功能.
3.9 版后已移除:
collections.abc.AsyncIterator
現已支持[]
。詳見(jiàn) PEP 585 和 GenericAlias 類(lèi)型。
- class typing.Awaitable(Generic[T_co])?
collections.abc.Awaitable
的泛型版本。3.5.2 新版功能.
3.9 版后已移除:
collections.abc.Awaitable
現已支持[]
。詳見(jiàn) PEP 585 和 GenericAlias 類(lèi)型。
上下文管理器類(lèi)型?
- class typing.ContextManager(Generic[T_co])?
contextlib.AbstractContextManager
的泛型版本。3.5.4 新版功能.
3.6.0 新版功能.
3.9 版后已移除:
contextlib.AbstractContextManager
現已支持[]
。詳見(jiàn) PEP 585 和 GenericAlias 類(lèi)型。
- class typing.AsyncContextManager(Generic[T_co])?
contextlib.AbstractAsyncContextManager
的泛型版本。3.5.4 新版功能.
3.6.2 新版功能.
3.9 版后已移除:
contextlib.AbstractAsyncContextManager
現已支持[]
。詳見(jiàn) PEP 585 和 GenericAlias 類(lèi)型。
協(xié)議?
這些協(xié)議由 runtime_checkable()
裝飾。
- class typing.SupportsAbs?
含抽象方法
__abs__
的抽象基類(lèi),是其返回類(lèi)型里的協(xié)變量。
- class typing.SupportsBytes?
含抽象方法
__bytes__
的抽象基類(lèi)。
- class typing.SupportsComplex?
含抽象方法
__complex__
的抽象基類(lèi)。
- class typing.SupportsFloat?
含抽象方法
__float__
的抽象基類(lèi)。
- class typing.SupportsIndex?
含抽象方法
__index__
的抽象基類(lèi)。3.8 新版功能.
- class typing.SupportsInt?
含抽象方法
__int__
的抽象基類(lèi)。
- class typing.SupportsRound?
含抽象方法
__round__
的抽象基類(lèi),是其返回類(lèi)型的協(xié)變量。
函數與裝飾器?
- typing.cast(typ, val)?
把值強制轉換為類(lèi)型。
不變更返回值。對類(lèi)型檢查器而言,代表了返回值具有指定的類(lèi)型,但運行時(shí)故意不做任何檢查(以便讓檢查速度盡量快)。
- typing.assert_type(val, typ, /)?
Ask a static type checker to confirm that val has an inferred type of typ.
When the type checker encounters a call to
assert_type()
, it emits an error if the value is not of the specified type:def greet(name: str) -> None: assert_type(name, str) # OK, inferred type of `name` is `str` assert_type(name, int) # type checker error
At runtime this returns the first argument unchanged with no side effects.
This function is useful for ensuring the type checker's understanding of a script is in line with the developer's intentions:
def complex_function(arg: object): # Do some complex type-narrowing logic, # after which we hope the inferred type will be `int` ... # Test whether the type checker correctly understands our function assert_type(arg, int)
3.11 新版功能.
- typing.assert_never(arg, /)?
Ask a static type checker to confirm that a line of code is unreachable.
Example:
def int_or_str(arg: int | str) -> None: match arg: case int(): print("It's an int") case str(): print("It's a str") case _ as unreachable: assert_never(unreachable)
Here, the annotations allow the type checker to infer that the last case can never execute, because
arg
is either anint
or astr
, and both options are covered by earlier cases. If a type checker finds that a call toassert_never()
is reachable, it will emit an error. For example, if the type annotation forarg
was insteadint | str | float
, the type checker would emit an error pointing out thatunreachable
is of typefloat
. For a call toassert_never
to pass type checking, the inferred type of the argument passed in must be the bottom type,Never
, and nothing else.At runtime, this throws an exception when called.
參見(jiàn)
Unreachable Code and Exhaustiveness Checking has more information about exhaustiveness checking with static typing.
3.11 新版功能.
- typing.reveal_type(obj, /)?
Reveal the inferred static type of an expression.
When a static type checker encounters a call to this function, it emits a diagnostic with the type of the argument. For example:
x: int = 1 reveal_type(x) # Revealed type is "builtins.int"
This can be useful when you want to debug how your type checker handles a particular piece of code.
The function returns its argument unchanged, which allows using it within an expression:
x = reveal_type(1) # Revealed type is "builtins.int"
Most type checkers support
reveal_type()
anywhere, even if the name is not imported fromtyping
. Importing the name fromtyping
allows your code to run without runtime errors and communicates intent more clearly.At runtime, this function prints the runtime type of its argument to stderr and returns it unchanged:
x = reveal_type(1) # prints "Runtime type is int" print(x) # prints "1"
3.11 新版功能.
- @typing.dataclass_transform?
dataclass_transform
may be used to decorate a class, metaclass, or a function that is itself a decorator. The presence of@dataclass_transform()
tells a static type checker that the decorated object performs runtime "magic" that transforms a class, giving itdataclasses.dataclass()
-like behaviors.Example usage with a decorator function:
T = TypeVar("T") @dataclass_transform() def create_model(cls: type[T]) -> type[T]: ... return cls @create_model class CustomerModel: id: int name: str
On a base class:
@dataclass_transform() class ModelBase: ... class CustomerModel(ModelBase): id: int name: str
On a metaclass:
@dataclass_transform() class ModelMeta(type): ... class ModelBase(metaclass=ModelMeta): ... class CustomerModel(ModelBase): id: int name: str
The
CustomerModel
classes defined above will be treated by type checkers similarly to classes created with@dataclasses.dataclass
. For example, type checkers will assume these classes have__init__
methods that acceptid
andname
.The arguments to this decorator can be used to customize this behavior:
eq_default
indicates whether theeq
parameter is assumed to beTrue
orFalse
if it is omitted by the caller.order_default
indicates whether theorder
parameter is assumed to be True or False if it is omitted by the caller.kw_only_default
indicates whether thekw_only
parameter is assumed to be True or False if it is omitted by the caller.field_specifiers
specifies a static list of supported classes or functions that describe fields, similar todataclasses.field()
.Arbitrary other keyword arguments are accepted in order to allow for possible future extensions.
At runtime, this decorator records its arguments in the
__dataclass_transform__
attribute on the decorated object. It has no other runtime effect.See PEP 681 for more details.
3.11 新版功能.
- @typing.overload?
@overload
裝飾器可以修飾支持多個(gè)不同參數類(lèi)型組合的函數或方法。@overload
- 裝飾定義的系列必須緊跟一個(gè)非@overload
-裝飾定義(用于同一個(gè)函數/方法)。@overload
-裝飾定義僅是為了協(xié)助類(lèi)型檢查器, 因為該裝飾器會(huì )被非@overload
-裝飾定義覆蓋,后者用于運行時(shí),而且會(huì )被類(lèi)型檢查器忽略。在運行時(shí)直接調用@overload
裝飾的函數會(huì )觸發(fā)NotImplementedError
。下面的重載示例給出了比聯(lián)合類(lèi)型或類(lèi)型變量更精準的類(lèi)型:@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>
詳見(jiàn) PEP 484,與其他類(lèi)型語(yǔ)義進(jìn)行對比。
在 3.11 版更改: Overloaded functions can now be introspected at runtime using
get_overloads()
.
- typing.get_overloads(func)?
Return a sequence of
@overload
-decorated definitions for func. func is the function object for the implementation of the overloaded function. For example, given the definition ofprocess
in the documentation for@overload
,get_overloads(process)
will return a sequence of three function objects for the three defined overloads. If called on a function with no overloads,get_overloads()
returns an empty sequence.get_overloads()
can be used for introspecting an overloaded function at runtime.3.11 新版功能.
- typing.clear_overloads()?
Clear all registered overloads in the internal registry. This can be used to reclaim the memory used by the registry.
3.11 新版功能.
- @typing.final?
告知類(lèi)型檢查器被裝飾的方法不能被覆蓋,且被裝飾的類(lèi)不能作為子類(lèi)的裝飾器,例如:
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 ...
這些屬性沒(méi)有運行時(shí)檢查。詳見(jiàn) PEP 591。
3.8 新版功能.
在 3.11 版更改: The decorator will now set the
__final__
attribute toTrue
on the decorated object. Thus, a check likeif getattr(obj, "__final__", False)
can be used at runtime to determine whether an objectobj
has been marked as final. If the decorated object does not support setting attributes, the decorator returns the object unchanged without raising an exception.
- @typing.no_type_check?
標明注解不是類(lèi)型提示的裝飾器。
This works as class or function decorator. With a class, it applies recursively to all methods and classes defined in that class (but not to methods defined in its superclasses or subclasses).
本方法可直接修改函數。
- @typing.no_type_check_decorator?
讓其他裝飾器具有
no_type_check()
效果的裝飾器。本裝飾器用
no_type_check()
里的裝飾函數打包其他裝飾器。
- @typing.type_check_only?
標記類(lèi)或函數內不可用于運行時(shí)的裝飾器。
在運行時(shí),該裝飾器本身不可用。實(shí)現返回的是私有類(lèi)實(shí)例時(shí),它主要是用于標記在類(lèi)型存根文件中定義的類(lèi)。
@type_check_only class Response: # private or not available at runtime code: int def get_header(self, name: str) -> str: ... def fetch_response() -> Response: ...
注意,建議不要返回私有類(lèi)實(shí)例,最好將之設為公共類(lèi)。
內省輔助器?
- typing.get_type_hints(obj, globalns=None, localns=None, include_extras=False)?
返回函數、方法、模塊、類(lèi)對象的類(lèi)型提示的字典。
This is often the same as
obj.__annotations__
. In addition, forward references encoded as string literals are handled by evaluating them inglobals
andlocals
namespaces. For a classC
, return a dictionary constructed by merging all the__annotations__
alongC.__mro__
in reverse order.本函數以遞歸地方式用
T
替換所有Annotated[T, ...]
, 除非將include_extras
的值設置為True
(詳見(jiàn)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'] }
備注
get_type_hints()
does not work with imported type aliases that include forward references. Enabling postponed evaluation of annotations (PEP 563) may remove the need for most forward references.在 3.9 版更改: PEP 593 的組成部分,添加了
include_extras
參數。在 3.11 版更改: Previously,
Optional[t]
was added for function and method annotations if a default value equal toNone
was set. Now the annotation is returned unchanged.
- typing.get_args(tp)?
- typing.get_origin(tp)?
為泛型類(lèi)型與特殊類(lèi)型形式提供了基本的內省功能。
For a typing object of the form
X[Y, Z, ...]
these functions returnX
and(Y, Z, ...)
. IfX
is a generic alias for a builtin orcollections
class, it gets normalized to the original class. IfX
is a union orLiteral
contained in another generic type, the order of(Y, Z, ...)
may be different from the order of the original arguments[Y, Z, ...]
due to type caching. For unsupported objects returnNone
and()
correspondingly. Examples: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.is_typeddict(tp)?
檢查一個(gè)類(lèi)型是否為
TypedDict
。例如:
class Film(TypedDict): title: str year: int is_typeddict(Film) # => True is_typeddict(list | str) # => False
3.10 新版功能.
- class typing.ForwardRef?
用于字符串前向引用的內部類(lèi)型表示的類(lèi)。 例如,
List["SomeClass"]
會(huì )被隱式轉換為List[ForwardRef("SomeClass")]
。 這個(gè)類(lèi)不應由用戶(hù)來(lái)實(shí)例化,但可以由內省工具使用。備注
PEP 585 泛型類(lèi)型例如
list["SomeClass"]
將不會(huì )被隱式地轉換為list[ForwardRef("SomeClass")]
因而將不會(huì )自動(dòng)解析為list[SomeClass]
。3.7.4 新版功能.
常量?
- typing.TYPE_CHECKING?
被第三方靜態(tài)類(lèi)型檢查器假定為
True
的特殊常量。 在運行時(shí)為False
。 用法如下:if TYPE_CHECKING: import expensive_mod def fun(arg: 'expensive_mod.SomeType') -> None: local_var: expensive_mod.AnotherType = other_fun()
第一個(gè)類(lèi)型注解必須用引號標注,才能把它當作“前向引用”,從而在解釋器運行時(shí)中隱藏
expensive_mod
引用。局部變量的類(lèi)型注釋不會(huì )被評估,因此,第二個(gè)注解不需要用引號引起來(lái)。備注
If
from __future__ import annotations
is used, annotations are not evaluated at function definition time. Instead, they are stored as strings in__annotations__
. This makes it unnecessary to use quotes around the annotation (see PEP 563).3.5.2 新版功能.
Deprecation Timeline of Major Features?
Certain features in typing
are deprecated and may be removed in a future
version of Python. The following table summarizes major deprecations for your
convenience. This is subject to change, and not all deprecations are listed.
Feature |
Deprecated in |
Projected removal |
PEP/issue |
---|---|---|---|
|
3.8 |
3.12 |
|
|
3.9 |
Undecided |
|
|
3.11 |
Undecided |