新聞中心
typing —— 類型注解支持
3.5 新版功能.

源碼: Lib/typing.py
備注
python 運(yùn)行時(shí)不強(qiáng)制執(zhí)行函數(shù)和變量類型注解,但這些注解可用于類型檢查器、IDE、靜態(tài)檢查器等第三方工具。
這個(gè)模塊提供對(duì)類型提示的運(yùn)行時(shí)支持。最基本的支持包括 Any , Union , Callable , TypeVar , 和 Generic 。關(guān)于完整的規(guī)范,請(qǐng)參考 PEP 484 。關(guān)于類型提示的簡(jiǎn)化介紹,請(qǐng)參考 PEP 483 。
下面的函數(shù)接收與返回的都是字符串,注解方式如下:
def greeting(name: str) -> str:return 'Hello ' + name
greeting 函數(shù)中,參數(shù) name 的類型是 str,返回類型也是 str。子類型也可以當(dāng)作參數(shù)。
新的功能頻繁地被添加到 typing 模塊中。typing_extensions 包提供了這些新功能對(duì)舊版本 Python 的向后移植。
For a summary of deprecated features and a deprecation timeline, please see Deprecation Timeline of Major Features.
參見
The documentation at https://typing.readthedocs.io/ serves as useful reference for type system features, useful typing related tools and typing best practices.
相關(guān)的 PEP
自從在 PEP 484 和 PEP 483 中首次引入類型提示以來(lái),一些 PEP 已經(jīng)修改和增強(qiáng)了 Python 的類型注釋框架。包括:
-
PEP 526: 變量注解的語(yǔ)法
引入 在函數(shù)定義之外標(biāo)注變量的語(yǔ)法,以及 ClassVar 。
-
PEP 544: Protocol:結(jié)構(gòu)子類型(靜態(tài)鴨子類型)。
引入 Protocol 和 @runtime_checkable 裝飾器。
-
PEP 585: 標(biāo)準(zhǔn)集合中的類型提示泛型
引入 types.GenericAlias 和使用標(biāo)準(zhǔn)庫(kù)類作為 通用類型 的能力。
-
PEP 586: 文字類型
引入 Literal
-
PEP 589: TypedDict: 具有固定鍵集的字典的類型提示
引入 TypedDict
-
PEP 591: 為 typing 添加最終限定符
引入 Final 和 @final 裝飾器
-
PEP 593: 靈活的函數(shù)和變量注解
引入 Annotated
-
PEP 604: 允許
X | Y形式的聯(lián)合類型寫法引入 types.UnionType 和使用二元或運(yùn)算符
|來(lái)表示 類型聯(lián)合 的能力。 -
PEP 612: 形參規(guī)格變量
引入 ParamSpec 和 Concatenate
-
PEP 613: 顯式類型別名
引入 TypeAlias
-
PEP 646: Variadic Generics
Introducing TypeVarTuple
-
PEP 647: 用戶自定義的類型保護(hù)器
引入 TypeGuard
-
PEP 655: Marking individual TypedDict items as required or potentially missing
Introducing Required and NotRequired
-
PEP 673: Self type
Introducing Self
-
PEP 675: Arbitrary Literal String Type
Introducing LiteralString
-
PEP 681: Data Class Transforms
Introducing the @dataclass_transform decorator
類型別名
把類型賦給別名,就可以定義類型別名。本例中,Vector 和 list[float] 相同,可互換:
Vector = list[float]def scale(scalar: float, vector: Vector) -> Vector:return [scalar * num for num in vector]# passes type checking; a list of floats qualifies as a Vector.new_vector = scale(2.0, [1.0, -4.2, 5.4])
類型別名適用于簡(jiǎn)化復(fù)雜的類型簽名。例如:
from collections.abc import SequenceConnectionOptions = dict[str, str]Address = tuple[str, int]Server = tuple[Address, ConnectionOptions]def broadcast_message(message: str, servers: Sequence[Server]) -> None:...# The static type checker will treat the previous type signature as# being exactly equivalent to this one.def broadcast_message(message: str,servers: Sequence[tuple[tuple[str, int], dict[str, str]]]) -> None:...
注意,None 是一種類型提示特例,已被 type(None) 取代。
NewType
使用 NewType 助手來(lái)創(chuàng)建不同的類型
from typing import NewTypeUserId = NewType('UserId', int)some_id = UserId(524313)
靜態(tài)類型檢查器把新類型當(dāng)作原始類型的子類,這種方式適用于捕捉邏輯錯(cuò)誤:
def get_user_name(user_id: UserId) -> str:...# passes type checkinguser_a = get_user_name(UserId(42351))# fails type checking; an int is not a UserIduser_b = get_user_name(-1)
UserId 類型的變量可執(zhí)行所有 int 操作,但返回結(jié)果都是 int 類型。這種方式允許在預(yù)期 int 時(shí)傳入 UserId,還能防止意外創(chuàng)建無(wú)效的 UserId:
# 'output' is of type 'int', not 'UserId'output = UserId(23413) + UserId(54341)
注意,這些檢查只由靜態(tài)類型檢查器強(qiáng)制執(zhí)行。在運(yùn)行時(shí),語(yǔ)句 Derived = NewType('Derived', Base) 將產(chǎn)生一個(gè) Derived 可調(diào)用對(duì)象,該對(duì)象立即返回你傳遞給它的任何參數(shù)。 這意味著語(yǔ)句 Derived(some_value) 不會(huì)創(chuàng)建一個(gè)新的類,也不會(huì)引入超出常規(guī)函數(shù)調(diào)用的很多開銷。
更確切地說(shuō),在運(yùn)行時(shí),some_value is Derived(some_value) 表達(dá)式總為 True。
創(chuàng)建 Derived 的子類型是無(wú)效的:
from typing import NewTypeUserId = NewType('UserId', int)# Fails at runtime and does not pass type checkingclass AdminUserId(UserId): pass
然而,我們可以在 “派生的” NewType 的基礎(chǔ)上創(chuàng)建一個(gè) NewType。
from typing import NewTypeUserId = NewType('UserId', int)ProUserId = NewType('ProUserId', UserId)
同時(shí),ProUserId 的類型檢查也可以按預(yù)期執(zhí)行。
詳見 PEP 484。
備注
回顧上文,類型別名聲明了兩種彼此 等價(jià) 的類型。 Alias = Original 時(shí),靜態(tài)類型檢查器認(rèn)為 Alias 與 Original 完全等價(jià)。 這種方式適用于簡(jiǎn)化復(fù)雜類型簽名。
反之,NewType 聲明把一種類型當(dāng)作另一種類型的 子類型。Derived = NewType('Derived', Original) 時(shí),靜態(tài)類型檢查器把 Derived 當(dāng)作 Original 的 子類 ,即,Original 類型的值不能用在預(yù)期 Derived 類型的位置。這種方式適用于以最小運(yùn)行時(shí)成本防止邏輯錯(cuò)誤。
3.5.2 新版功能.
在 3.10 版更改: NewType 現(xiàn)在是一個(gè)類而不是一個(gè)函數(shù)。 在調(diào)用 NewType 而不是普通的函數(shù)時(shí),會(huì)有一些額外的運(yùn)行時(shí)間成本。 然而,這種開銷將在 3.11.0 中減少。
可調(diào)對(duì)象(Callable)
預(yù)期特定簽名回調(diào)函數(shù)的框架可以用 Callable[[Arg1Type, Arg2Type], ReturnType] 實(shí)現(xiàn)類型提示。
例如:
from collections.abc import Callabledef feeder(get_next_item: Callable[[], str]) -> None:# Bodydef async_query(on_success: Callable[[int], None],on_error: Callable[[int, Exception], None]) -> None:# Bodyasync def on_update(value: str) -> None:# Bodycallback: Callable[[str], Awaitable[None]] = on_update
無(wú)需指定調(diào)用簽名,用省略號(hào)字面量替換類型提示里的參數(shù)列表: Callable[..., ReturnType],就可以聲明可調(diào)對(duì)象的返回類型。
以其他可調(diào)用對(duì)象為參數(shù)的可調(diào)用對(duì)象可以使用 ParamSpec 來(lái)表明其參數(shù)類型是相互依賴的。此外,如果該可調(diào)用對(duì)象增加或刪除了其他可調(diào)用對(duì)象的參數(shù),可以使用 Concatenate 操作符。 它們分別采取``Callable[ParamSpecVariable, ReturnType]`` 和 Callable[Concatenate[Arg1Type, Arg2Type, ..., ParamSpecVariable], ReturnType] 的形式。
在 3.10 版更改: Callable now supports ParamSpec and Concatenate. See PEP 612 for more details.
參見
ParamSpec 和 Concatenate 的文檔提供了在 Callable 中使用的例子。
泛型(Generic)
容器中,對(duì)象的類型信息不能以泛型方式靜態(tài)推斷,因此,抽象基類擴(kuò)展支持下標(biāo),用于表示容器元素的預(yù)期類型。
from collections.abc import Mapping, Sequencedef notify_by_email(employees: Sequence[Employee],overrides: Mapping[str, str]) -> None: ...
typing 模塊中推出的 TypeVar 工廠函數(shù)實(shí)現(xiàn)泛型參數(shù)化。
from collections.abc import Sequencefrom typing import TypeVarT = TypeVar('T') # Declare type variabledef first(l: Sequence[T]) -> T: # Generic functionreturn l[0]
用戶定義的泛型類型
用戶定義的類可以定義為泛型類。
from typing import TypeVar, Genericfrom logging import LoggerT = TypeVar('T')class LoggedVar(Generic[T]):def __init__(self, value: T, name: str, logger: Logger) -> None:self.name = nameself.logger = loggerself.value = valuedef set(self, new: T) -> None:self.log('Set ' + repr(self.value))self.value = newdef get(self) -> T:self.log('Get ' + repr(self.value))return self.valuedef log(self, message: str) -> None:self.logger.info('%s: %s', self.name, message)
Generic[T] 是定義類 LoggedVar 的基類,該類使用單類型參數(shù) T。在該類體內(nèi),T 是有效的類型。
The Generic base class defines __class_getitem__() so that LoggedVar[T] is valid as a type:
from collections.abc import Iterabledef zero_all_vars(vars: Iterable[LoggedVar[int]]) -> None:for var in vars:var.set(0)
一個(gè)泛型可以有任何數(shù)量的類型變量。所有種類的 TypeVar 都可以作為泛型的參數(shù):
from typing import TypeVar, Generic, SequenceT = TypeVar('T', contravariant=True)B = TypeVar('B', bound=Sequence[bytes], covariant=True)S = TypeVar('S', int, str)class WeirdTrio(Generic[T, B, S]):...
Generic 類型變量的參數(shù)應(yīng)各不相同。下列代碼就是無(wú)效的:
from typing import TypeVar, Generic...T = TypeVar('T')class Pair(Generic[T, T]): # INVALID...
Generic 支持多重繼承:
from collections.abc import Sizedfrom typing import TypeVar, GenericT = TypeVar('T')class LinkedList(Sized, Generic[T]):...
繼承自泛型類時(shí),可以修正某些類型變量:
from collections.abc import Mappingfrom typing import TypeVarT = TypeVar('T')class MyDict(Mapping[str, T]):...
比如,本例中 MyDict 調(diào)用的單參數(shù),T。
未指定泛型類的類型參數(shù)時(shí),每個(gè)位置的類型都預(yù)設(shè)為 Any。下例中,MyIterable 不是泛型,但卻隱式繼承了 Iterable[Any]:
from collections.abc import Iterableclass MyIterable(Iterable): # Same as Iterable[Any]
還支持用戶定義的泛型類型別名。例如:
from collections.abc import Iterablefrom typing import TypeVarS = TypeVar('S')Response = Iterable[S] | int# Return type here is same as Iterable[str] | intdef 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 不再支持自定義元類。
用戶定義的參數(shù)表達(dá)式的泛型也通過(guò) Generic[P] 形式的參數(shù)規(guī)范變量來(lái)支持。該行為與上面描述的類型變量一致,因?yàn)閰?shù)規(guī)范變量被類型化模塊視為一個(gè)專門的類型變量。 這方面的一個(gè)例外是,一個(gè)類型列表可以用來(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, (, )]
此外,一個(gè)只有一個(gè)參數(shù)規(guī)范變量的泛型將接受表格 X[[Type1, Type2, ...]] 中的參數(shù)列表,出于美觀的考慮也包括 X[Type1, Type2, ...] 。 在內(nèi)部,后者被轉(zhuǎn)換為前者,所以下面的內(nèi)容是等價(jià)的:
>>> class X(Generic[P]): ......>>> X[int, str]__main__.X[(, )] >>> X[[int, str]]__main__.X[(, )]
請(qǐng)注意,帶有 ParamSpec 的泛型在某些情況下可能不會(huì)有正確的``__parameters__``,因?yàn)樗鼈冎饕糜陟o態(tài)類型檢查。
在 3.10 版更改: Generic 現(xiàn)在可以通過(guò)參數(shù)表達(dá)式進(jìn)行參數(shù)化。參見 ParamSpec 和 PEP 612 以了解更多細(xì)節(jié)。
抽象基類可作為用戶定義的泛型類的基類,且不會(huì)與元類沖突?,F(xiàn)已不再支持泛型元類。參數(shù)化泛型的輸出結(jié)果會(huì)被緩存,typing 模塊的大多數(shù)類型都可哈希、可進(jìn)行等價(jià)對(duì)比。
Any 類型
Any 是一種特殊的類型。靜態(tài)類型檢查器認(rèn)為所有類型均與 Any 兼容,同樣,Any 也與所有類型兼容。
也就是說(shuō),可對(duì) Any 類型的值執(zhí)行任何操作或方法調(diào)用,并賦值給任意變量:
from typing import Anya: Any = Nonea = [] # OKa = 2 # OKs: str = ''s = a # OKdef foo(item: Any) -> int:# Passes type checking; 'item' could be any type,# and that type might have a 'bar' methoditem.bar()...
Notice that no type checking is performed when assigning a value of type Any to a more precise type. For example, the static type checker did not report an error when assigning a to s even though s was declared to be of type str and receives an int value at runtime!
此外,未指定返回值與參數(shù)類型的函數(shù),都隱式地默認(rèn)使用 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)類型代碼時(shí),此操作把 Any 當(dāng)作 應(yīng)急出口。
Any 和 object 的區(qū)別。與 Any 相似,所有類型都是 object 的子類型。然而,與 Any 不同,object 不可逆:object 不是 其它類型的子類型。
就是說(shuō),值的類型是 object 時(shí),類型檢查器幾乎會(huì)拒絕所有對(duì)它的操作,并且,把它賦給更精確的類型變量(或返回值)屬于類型錯(cuò)誤。例如:
def hash_a(item: object) -> int:# Fails type checking; an object does not have a 'magic' method.item.magic()...def hash_b(item: Any) -> int:# Passes type checkingitem.magic()...# Passes type checking, since ints and strs are subclasses of objecthash_a(42)hash_a("foo")# Passes type checking, since Any is compatible with all typeshash_b(42)hash_b("foo")
使用 object,說(shuō)明值能以類型安全的方式轉(zhuǎn)為任何類型。使用 Any,說(shuō)明值是動(dòng)態(tài)類型。
名義子類型 vs 結(jié)構(gòu)子類型
最初 PEP 484 將 Python 靜態(tài)類型系統(tǒng)定義為使用 名義子類型。這意味著當(dāng)且僅當(dāng)類 A 是 B 的子類時(shí),才滿足有類 B 預(yù)期時(shí)使用類 A 。
此項(xiàng)要求以前也適用于抽象基類,例如,Iterable 。這種方式的問(wèn)題在于,定義類時(shí)必須顯式說(shuō)明,既不 Pythonic,也不是動(dòng)態(tài)類型式 Python 代碼的慣用寫法。例如,下列代碼就遵從了 PEP 484 的規(guī)范:
from collections.abc import Sized, Iterable, Iteratorclass Bucket(Sized, Iterable[int]):...def __len__(self) -> int: ...def __iter__(self) -> Iterator[int]: ...
PEP 544 允許用戶在類定義時(shí)不顯式說(shuō)明基類,從而解決了這一問(wèn)題,靜態(tài)類型檢查器隱式認(rèn)為 Bucket 既是 Sized 的子類型,又是 Iterable[int] 的子類型。這就是 結(jié)構(gòu)子類型 (又稱為靜態(tài)鴨子類型):
from collections.abc import Iterator, Iterableclass 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
此外,結(jié)構(gòu)子類型的優(yōu)勢(shì)在于,通過(guò)繼承特殊類 Protocol ,用戶可以定義新的自定義協(xié)議(見下文中的例子)。
模塊內(nèi)容
本模塊定義了下列類、函數(shù)和修飾器。
備注
本模塊定義了一些類型,作為標(biāo)準(zhǔn)庫(kù)中已有的類的子類,從而可以讓 Generic 支持 [] 中的類型變量。Python 3.9 中,這些標(biāo)準(zhǔn)庫(kù)的類已支持 [] ,因此,這些類型就變得冗余了。
Python 3.9 棄用了這些冗余類型,但解釋器并未提供相應(yīng)的棄用警告。標(biāo)記棄用類型的工作留待支持 Python 3.9 及以上版本的類型檢查器實(shí)現(xiàn)。
Python 3.9.0 發(fā)布五年后的首個(gè) Python 發(fā)行版將從 typing 模塊中移除這些棄用類型。詳見 PEP 585 《標(biāo)準(zhǔn)集合的類型提示泛型》。
特殊類型原語(yǔ)
特殊類型
這些類型可用于類型注解,但不支持 []。
typing.Any
不受限的特殊類型。
-
所有類型都與 Any 兼容。
-
Any 與所有類型都兼容。
在 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") # okrun_query(literal_string) # okrun_query("SELECT * FROM " + literal_string) # okrun_query(arbitrary_string) # type checker errorrun_query( # type checker errorf"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.
See PEP 675 for more details.
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 Neverdef never_call_me(arg: Never) -> None:passdef int_or_str(arg: int | str) -> None:never_call_me(arg) # type checker errormatch 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
標(biāo)記沒(méi)有返回值的函數(shù)的特殊類型。例如:
from typing import NoReturndef 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 Selfclass Foo:def return_self(self) -> Self:...return self
This annotation is semantically equivalent to the following, albeit in a more succinct fashion:
from typing import TypeVarSelf = TypeVar("Self", bound="Foo")class Foo:def return_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 Self as calls to SubclassOfFoo.return_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
clsparameter. -
Annotating an __enter__() method which returns self.
See PEP 673 for more details.
3.11 新版功能.
typing.TypeAlias
用于顯式聲明 類型別名 的特殊標(biāo)注。 例如:
from typing import TypeAliasFactors: TypeAlias = list[int]
關(guān)于顯式類型別名的更多細(xì)節(jié),請(qǐng)參見 PEP 613。
3.10 新版功能.
特殊形式
可用于類型注解,且支持 [] ,每種形式都有其獨(dú)特的句法。
typing.Tuple
元組類型; Tuple[X, Y] 是二項(xiàng)元組類型,第一個(gè)元素的類型是 X,第二個(gè)元素的類型是 Y??赵M的類型可寫為 Tuple[()]。
例:Tuple[T1, T2] 是二項(xiàng)元組,類型變量分別為 T1 和 T2。Tuple[int, float, str] 是由整數(shù)、浮點(diǎn)數(shù)、字符串組成的三項(xiàng)元組。
可用省略號(hào)字面量指定同質(zhì)變長(zhǎng)元組,例如,Tuple[int, ...] 。Tuple 與 Tuple[Any, ...] 等價(jià),也與 tuple 等價(jià)。
3.9 版后已移除: builtins.tuple now supports subscripting ([]). See PEP 585 and GenericAlias 類型.
typing.Union
聯(lián)合類型; Union[X, Y] 等價(jià)于 X | Y ,意味著滿足 X 或 Y 之一。
要定義一個(gè)聯(lián)合類型,可以使用類似 Union[int, str] 或簡(jiǎn)寫 int | str。建議使用這種簡(jiǎn)寫。細(xì)節(jié):
-
參數(shù)必須是某種類型,且至少有一個(gè)。
-
聯(lián)合類型之聯(lián)合類型會(huì)被展平,例如:
Union[Union[int, str], float] == Union[int, str, float]
-
單參數(shù)之聯(lián)合類型就是該參數(shù)自身,例如:
Union[int] == int # The constructor actually returns int
-
冗余的參數(shù)會(huì)被跳過(guò),例如:
Union[int, str, int] == Union[int, str] == int | str
-
比較聯(lián)合類型,不涉及參數(shù)順序,例如:
Union[int, str] == Union[str, int]
-
Union不能作為子類,也不能實(shí)例化。 -
不支持
Union[X][Y]這種寫法。
在 3.7 版更改: 在運(yùn)行時(shí),不要移除聯(lián)合類型中的顯式子類。
在 3.10 版更改: 聯(lián)合類型現(xiàn)在可以寫成 X | Y。 參見 聯(lián)合類型表達(dá)式。
typing.Optional
可選類型。
Optional[X] 等價(jià)于 X | None (或 Union[X, None] ) 。
注意,可選類型與含默認(rèn)值的可選參數(shù)不同。含默認(rèn)值的可選參數(shù)不需要在類型注解上添加 Optional 限定符,因?yàn)樗鼉H是可選的。例如:
def foo(arg: int = 0) -> None:...
另一方面,顯式應(yīng)用 None 值時(shí),不管該參數(shù)是否可選, Optional 都適用。例如:
def foo(arg: Optional[int] = None) -> None:...
在 3.10 版更改: 可選參數(shù)現(xiàn)在可以寫成 X | None。 參見 聯(lián)合類型表達(dá)式。
typing.Callable
可調(diào)類型; Callable[[int], str] 是把(int)轉(zhuǎn)為 str 的函數(shù)。
下標(biāo)句法必須與參數(shù)列表和返回類型這兩個(gè)值一起使用。參數(shù)列表只能是類型列表或省略號(hào);返回類型只能是單一類型。
沒(méi)有說(shuō)明可選參數(shù)或關(guān)鍵字參數(shù)的句法;這類函數(shù)類型很少用作回調(diào)類型。Callable[..., ReturnType] (省略號(hào)字面量)可用于為接受任意數(shù)量參數(shù),并返回 ReturnType 的可調(diào)對(duì)象提供類型提示。純 Callable 等價(jià)于 Callable[..., Any],進(jìn)而等價(jià)于 collections.abc.Callable 。
以其他可調(diào)用對(duì)象為參數(shù)的可調(diào)用對(duì)象可以使用 ParamSpec 來(lái)表明其參數(shù)類型是相互依賴的。此外,如果該可調(diào)用對(duì)象增加或刪除了其他可調(diào)用對(duì)象的參數(shù),可以使用 Concatenate 操作符。 它們分別采取``Callable[ParamSpecVariable, ReturnType]`` 和 Callable[Concatenate[Arg1Type, Arg2Type, ..., ParamSpecVariable], ReturnType] 的形式。
3.9 版后已移除: collections.abc.Callable now supports subscripting ([]). See PEP 585 and GenericAlias 類型.
在 3.10 版更改: Callable now supports ParamSpec and Concatenate. See PEP 612 for more details.
參見
ParamSpec 和 Concatenate 的文檔提供了使用 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,它為被裝飾的函數(shù)提供了 threading.Lock,Concatenate 可以用來(lái)表示 with_lock 期望一個(gè)可調(diào)用對(duì)象,該對(duì)象接收一個(gè) Lock 作為第一個(gè)參數(shù),并返回一個(gè)具有不同類型簽名的可調(diào)用對(duì)象。 在這種情況下,ParamSpec 表示返回的可調(diào)用對(duì)象的參數(shù)類型取決于被傳入的可調(diào)用程序的參數(shù)類型:
from collections.abc import Callablefrom threading import Lockfrom typing import Concatenate, ParamSpec, TypeVarP = 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_lockdef 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 新版功能.
參見
-
PEP 612 — 參數(shù)規(guī)范變量(引入
ParamSpec和Concatenate的 PEP)。 -
ParamSpec 和 Callable。
class typing.Type(Generic[CT_co])
用 C 注解的變量可以接受類型 C 的值。反之,用 Type[C] 注解的變量可以接受類自身的值 — 準(zhǔn)確地說(shuō),是接受 C 的 類對(duì)象,例如:
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當(dāng)前文章:創(chuàng)新互聯(lián)Python教程:typing——類型注解支持
文章來(lái)源:http://fisionsoft.com.cn/article/dghhjgg.html


咨詢
建站咨詢
