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:

類(lèi)型別名?

把類(lèi)型賦給別名,就可以定義類(lèi)型別名。本例中,Vectorlist[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)型檢查器認為 AliasOriginal 完全等價(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 現在支持 ParamSpecConcatenate。 更多信息見(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)型檢查。

在 3.10 版更改: Generic 現在可以通過(guò)參數表達式進(jìn)行參數化。參見(jiàn) ParamSpecPEP 612 以了解更多細節。

抽象基類(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 當作 應急出口。

Anyobject 的區別。與 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)型。

  • 所有類(lèi)型都與 Any 兼容。

  • 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 another LiteralString, but an object typed as just str is not. A string created by composing LiteralString-typed objects is also acceptable as a LiteralString.

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, the Never 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 to SubclassOfFoo.returns_self would have Foo as the return type and not SubclassOfFoo.

Other common use cases include:

  • classmethods that are used as alternative constructors and return instances of the cls parameter.

  • Annotating an __enter__() method which returns self.

For more information, see PEP 673.

3.11 新版功能.

typing.TypeAlias?

用于顯式聲明 類(lèi)型別名 的特殊標注。 例如:

from typing import TypeAlias

Factors: TypeAlias = list[int]

關(guān)于顯式類(lèi)型別名的更多細節,請參見(jiàn) PEP 613。

3.10 新版功能.

特殊形式?

可用于類(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, ...] 。TupleTuple[Any, ...] 等價(jià),也與 tuple 等價(jià)。

3.9 版后已移除: builtins.tuple 現已支持 []。詳見(jiàn) PEP 585GenericAlias 類(lèi)型。

typing.Union?

Union type; Union[X, Y] is equivalent to X | Y and means either X or Y.

To define a union, use e.g. Union[int, str] or the shorthand int | 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 to X | None (or Union[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 585GenericAlias 類(lèi)型。

在 3.10 版更改: Callable 現在支持 ParamSpecConcatenate。 更多信息見(jiàn) PEP 612。

參見(jiàn)

ParamSpecConcatenate 的文檔提供了使用 Callable 的例子。

typing.Concatenate?

Used with Callable and ParamSpec to type annotate a higher order callable which adds, removes, or transforms parameters of another callable. Usage is in the form Concatenate[Arg1Type, Arg2Type, ..., ParamSpecVariable]. Concatenate is currently only valid when used as the first argument to a Callable. The last parameter to Concatenate must be a ParamSpec 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 新版功能.

參見(jiàn)

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 585GenericAlias 類(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 新版功能.

在 3.9.1 版更改: Literal 現在能去除形參的重復。 Literal 對象的相等性比較不再依賴(lài)順序。 現在如果有某個(gè)參數不為 hashable,Literal 對象在相等性比較期間將引發(fā) TypeError。

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, as Annotated is variadic). Specifically, a type T can be annotated with metadata x via the typehint Annotated[T, x]. This metadata can be used for either static analysis or at runtime. If a library (or tool) encounters a typehint Annotated[T, x] and has no special logic for metadata x, it should ignore it and simply treat the type as T. Unlike the no_type_check functionality that currently exists in the typing module which completely disables typechecking annotations on a function or a class, the Annotated type allows for both static typechecking of T (which can safely ignore x) together with runtime access to x 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=Trueget_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)型檢查器:

  1. 返回值是一個(gè)布爾值。

  2. 如果返回值是 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)型映射到 clsself 之后的第二個(gè)參數的類(lèi)型。

簡(jiǎn)而言之,def foo(arg: TypeA) -> TypeGuard[TypeB]: ... 形式的意思是:如果 foo(arg) 返回 True,那么 arg 將把 TypeA 縮小為 TypeB。

備注

TypeB need not be a narrower form of TypeA -- it can even be a wider form. The main reason is to allow for things like narrowing list[object] to list[str] even though the latter is not a subtype of the former, since list 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 or contravariant=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 * in tuple[T, *Ts]. Conceptually, you can think of Ts as a tuple of type variables (T1, T2, ...). tuple[T, *Ts] would then become tuple[T, *(T1, T2, ...)], which is equivalent to tuple[T, T1, T2, ...]. (Note that in older versions of Python, you might see this written using Unpack instead, as Unpack[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 are int - *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 to call_soon match the types of the (positional) arguments of callback.

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 a type variable tuple is equivalent to using Unpack 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 see Unpack 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]。

  1. 類(lèi)型檢查器不能對 inner 函數進(jìn)行類(lèi)型檢查,因為 *args**kwargs 的類(lèi)型必須是 Any。

  2. cast() 在返回 inner 函數時(shí),可能需要在 add_logging 裝飾器的主體中進(jìn)行,或者必須告訴靜態(tài)類(lèi)型檢查器忽略 return inner。

args?
kwargs?

由于 ParamSpec 同時(shí)捕獲了位置參數和關(guān)鍵字參數,P.argsP.kwargs 可以用來(lái)將 ParamSpec 分割成其組成部分。 P.args 代表給定調用中的位置參數的元組,只能用于注釋 *args。 P.kwargs 代表給定調用中的關(guān)鍵字參數到其值的映射,只能用于注釋 **kwargs。在運行時(shí),P.argsP.kwargs 分別是 ParamSpecArgsParamSpecKwargs 的實(shí)例。

covariant=Truecontravariant=True 創(chuàng )建的參數規范變量可以用來(lái)聲明協(xié)變或禁變的通用類(lèi)型。 參數 bound 也被接受,類(lèi)似于 TypeVar。 然而這些關(guān)鍵字的實(shí)際語(yǔ)義還有待決定。

3.10 新版功能.

備注

只有在全局范圍內定義的參數規范變量可以被 pickle。

參見(jiàn)

typing.ParamSpecArgs?
typing.ParamSpecKwargs?

ParamSpec`的參數和關(guān)鍵字參數屬性。``ParamSpec`P.args 屬性是 ParamSpecArgs 的一個(gè)實(shí)例,P.kwargsParamSpecKwargs 的一個(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 a constrained type variable defined as AnyStr = 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.abcIterable 非常類(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 the namedtuple() 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è)字面的 FalseTrue 作為 total 參數的值。 True 是默認的,它使類(lèi)主體中定義的所有項目都是必需的。

It is possible for a TypedDict type to inherit from one or more other TypedDict types using the class-based syntax. Usage:

class Point3D(Point2D):
    z: int

Point3D has three items: x, y and z. 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 for Generic. 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 the total 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__ and Point2D.__optional_keys__ return frozenset objects containing required and non-required keys, respectively. Currently the only way to declare both required and non-required keys in the same TypedDict is mixed inheritance, declaring a TypedDict with one value for the total argument and then inheriting it from another TypedDict with a different value for total. 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 TypedDicts.

泛型具象容器?

對應的內置類(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 585GenericAlias 類(lèi)型。

class typing.List(list, MutableSequence[T])?

list 的泛型版本。適用于注解返回類(lèi)型。注解參數時(shí),最好使用 SequenceIterable 等抽象容器類(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 585GenericAlias 類(lèi)型。

class typing.Set(set, MutableSet[T])?

builtins.set 的泛型版本。適用于注解返回類(lèi)型。注解參數時(shí),最好使用 AbstractSet 等抽象容器類(lèi)型。

3.9 版后已移除: builtins.set 現已支持 []。詳見(jiàn) PEP 585GenericAlias 類(lèi)型。

class typing.FrozenSet(frozenset, AbstractSet[T_co])?

builtins.frozenset 的泛型版本。

3.9 版后已移除: builtins.frozenset 現已支持 []。詳見(jiàn) PEP 585GenericAlias 類(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 585GenericAlias 類(lèi)型。

class typing.OrderedDict(collections.OrderedDict, MutableMapping[KT, VT])?

collections.OrderedDict 的泛型版本。

3.7.2 新版功能.

3.9 版后已移除: collections.OrderedDict 現已支持 []。詳見(jiàn) PEP 585GenericAlias 類(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 585GenericAlias 類(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 585GenericAlias 類(lèi)型。

class typing.Deque(deque, MutableSequence[T])?

collections.deque 的泛型版本。

3.5.4 新版功能.

3.6.1 新版功能.

3.9 版后已移除: collections.deque 現已支持 []。詳見(jiàn) PEP 585GenericAlias 類(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 from typing 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 from typing instead.

3.9 版后已移除: re 模塊中的 PatternMatch 類(lèi)現已支持 []。詳見(jiàn) PEP 585GenericAlias 類(lèi)型。

class typing.Text?

Textstr 的別名。提供了對 Python 2 代碼的向下兼容:Python 2 中,Textunicode 的別名。

使用 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 of Text wherever possible.

抽象基類(lèi)?

collections.abc 對應的容器?

class typing.AbstractSet(Sized, Collection[T_co])?

collections.abc.Set 的泛型版本。

3.9 版后已移除: collections.abc.Set 現已支持 []。詳見(jiàn) PEP 585GenericAlias 類(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 585GenericAlias 類(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 585GenericAlias 類(lèi)型。

class typing.Container(Generic[T_co])?

collections.abc.Container 的泛型版本。

3.9 版后已移除: collections.abc.Container 現已支持 []。詳見(jiàn) PEP 585GenericAlias 類(lèi)型。

class typing.ItemsView(MappingView, Generic[KT_co, VT_co])?

collections.abc.ItemsView 的泛型版本。

3.9 版后已移除: collections.abc.ItemsView 現已支持 []。詳見(jiàn) PEP 585GenericAlias 類(lèi)型。

class typing.KeysView(MappingView[KT_co], AbstractSet[KT_co])?

collections.abc.KeysView 的泛型版本。

3.9 版后已移除: collections.abc.KeysView 現已支持 []。詳見(jiàn) PEP 585GenericAlias 類(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 585GenericAlias 類(lèi)型。

class typing.MappingView(Sized, Iterable[T_co])?

collections.abc.MappingView 的泛型版本。

3.9 版后已移除: collections.abc.MappingView 現已支持 []。詳見(jiàn) PEP 585GenericAlias 類(lèi)型。

class typing.MutableMapping(Mapping[KT, VT])?

collections.abc.MutableMapping 的泛型版本。

3.9 版后已移除: collections.abc.MutableMapping 現已支持 []。詳見(jiàn) PEP 585GenericAlias 類(lèi)型。

class typing.MutableSequence(Sequence[T])?

collections.abc.MutableSequence 的泛型版本。

3.9 版后已移除: collections.abc.MutableSequence 現已支持 []。詳見(jiàn) PEP 585GenericAlias 類(lèi)型。

class typing.MutableSet(AbstractSet[T])?

collections.abc.MutableSet 的泛型版本。

3.9 版后已移除: collections.abc.MutableSet 現已支持 []。詳見(jiàn) PEP 585GenericAlias 類(lèi)型。

class typing.Sequence(Reversible[T_co], Collection[T_co])?

collections.abc.Sequence 的泛型版本。

3.9 版后已移除: collections.abc.Sequence 現已支持 []。詳見(jiàn) PEP 585GenericAlias 類(lèi)型。

class typing.ValuesView(MappingView[VT_co])?

collections.abc.ValuesView 的泛型版本。

3.9 版后已移除: collections.abc.ValuesView 現已支持 []。詳見(jiàn) PEP 585GenericAlias 類(lèi)型。

collections.abc 對應的其他類(lèi)型?

class typing.Iterable(Generic[T_co])?

collections.abc.Iterable 的泛型版本。

3.9 版后已移除: collections.abc.Iterable 現已支持 []。詳見(jiàn) PEP 585GenericAlias 類(lèi)型。

class typing.Iterator(Iterable[T_co])?

collections.abc.Iterator 的泛型版本。

3.9 版后已移除: collections.abc.Iterator 現已支持 []。詳見(jiàn) PEP 585GenericAlias 類(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 模塊里的其他泛型不同, GeneratorSendType 屬于逆變行為,不是協(xié)變行為,也是不變行為。

如果生成器只產(chǎn)生值,可將 SendTypeReturnType 設為 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 585GenericAlias 類(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 585GenericAlias 類(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 585GenericAlias 類(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 585GenericAlias 類(lèi)型。

class typing.AsyncIterable(Generic[T_co])?

collections.abc.AsyncIterable 的泛型版本。

3.5.2 新版功能.

3.9 版后已移除: collections.abc.AsyncIterable 現已支持 []。詳見(jiàn) PEP 585GenericAlias 類(lèi)型。

class typing.AsyncIterator(AsyncIterable[T_co])?

collections.abc.AsyncIterator 的泛型版本。

3.5.2 新版功能.

3.9 版后已移除: collections.abc.AsyncIterator 現已支持 []。詳見(jiàn) PEP 585GenericAlias 類(lèi)型。

class typing.Awaitable(Generic[T_co])?

collections.abc.Awaitable 的泛型版本。

3.5.2 新版功能.

3.9 版后已移除: collections.abc.Awaitable 現已支持 []。詳見(jiàn) PEP 585GenericAlias 類(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 585GenericAlias 類(lèi)型。

class typing.AsyncContextManager(Generic[T_co])?

contextlib.AbstractAsyncContextManager 的泛型版本。

3.5.4 新版功能.

3.6.2 新版功能.

3.9 版后已移除: contextlib.AbstractAsyncContextManager 現已支持 []。詳見(jiàn) PEP 585GenericAlias 類(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 an int or a str, and both options are covered by earlier cases. If a type checker finds that a call to assert_never() is reachable, it will emit an error. For example, if the type annotation for arg was instead int | str | float, the type checker would emit an error pointing out that unreachable is of type float. For a call to assert_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 from typing. Importing the name from typing 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 it dataclasses.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 accept id and name.

The arguments to this decorator can be used to customize this behavior:

  • eq_default indicates whether the eq parameter is assumed to be True or False if it is omitted by the caller.

  • order_default indicates whether the order parameter is assumed to be True or False if it is omitted by the caller.

  • kw_only_default indicates whether the kw_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 to dataclasses.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 of process 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 to True on the decorated object. Thus, a check like if getattr(obj, "__final__", False) can be used at runtime to determine whether an object obj 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 in globals and locals namespaces. For a class C, return a dictionary constructed by merging all the __annotations__ along C.__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 to None 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 return X and (Y, Z, ...). If X is a generic alias for a builtin or collections class, it gets normalized to the original class. If X is a union or Literal 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 return None 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

typing.io and typing.re submodules

3.8

3.12

bpo-38291

typing versions of standard collections

3.9

Undecided

PEP 585

typing.Text

3.11

Undecided

gh-92332