typing --- 類型標(biāo)注支持?

3.5 新版功能.

源碼: Lib/typing.py

注解

?Python 運(yùn)行時(shí)并不強(qiáng)制標(biāo)注函數(shù)和變量類型。類型標(biāo)注可被用于第三方工具,比如類型檢查器、集成開發(fā)環(huán)境、靜態(tài)檢查器等。


此模塊支持 PEP 484PEP 526 指定的類型提示。最基本的支持由 AnyUnionTupleCallableTypeVarGeneric 類型組成。有關(guān)完整的規(guī)范,請(qǐng)參閱 PEP 484。有關(guān)類型提示的簡(jiǎn)單介紹,請(qǐng)參閱 PEP 483

函數(shù)接受并返回一個(gè)字符串,注釋像下面這樣:

def greeting(name: str) -> str:
    return 'Hello ' + name

在函數(shù) greeting 中,參數(shù) name 預(yù)期是 str 類型,并且返回 str 類型。子類型允許作為參數(shù)。

類型別名?

類型別名通過將類型分配給別名來定義。在這個(gè)例子中, VectorList[float] 將被視為可互換的同義詞:

from typing import List
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])

類型別名可用于簡(jiǎn)化復(fù)雜類型簽名。例如:

from typing import Dict, Tuple, 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:
    ...

請(qǐng)注意,None 作為類型提示是一種特殊情況,并且由 type(None) 取代。

NewType?

使用 NewType() 輔助函數(shù)創(chuàng)建不同的類型:

from typing import NewType

UserId = NewType('UserId', int)
some_id = UserId(524313)

靜態(tài)類型檢查器會(huì)將新類型視為它是原始類型的子類。這對(duì)于幫助捕捉邏輯錯(cuò)誤非常有用:

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)

您仍然可以對(duì) UserId 類型的變量執(zhí)行所有的 int 支持的操作,但結(jié)果將始終為 int 類型。這可以讓你在需要 int 的地方傳入 UserId,但會(huì)阻止你以無效的方式無意中創(chuàng)建 UserId:

# 'output' is of type 'int', not 'UserId'
output = UserId(23413) + UserId(54341)

注意,這些檢查只由靜態(tài)類型檢查器強(qiáng)制執(zhí)行。 在運(yùn)行時(shí),語句 Derived = NewType('Derived', Base) 將產(chǎn)生一個(gè) Derived 函數(shù),該函數(shù)立即返回你傳遞給它的任何參數(shù)。 這意味著表達(dá)式 Derived(some_value) 不會(huì)創(chuàng)建一個(gè)新的類,也不會(huì)引入超出常規(guī)函數(shù)調(diào)用的很多開銷。

更確切地說,表達(dá)式 some_value is Derived(some_value) 在運(yùn)行時(shí)總是為真。

這也意味著無法創(chuàng)建 Derived 的子類型,因?yàn)樗沁\(yùn)行時(shí)的標(biāo)識(shí)函數(shù),而不是實(shí)際的類型:

from typing import NewType

UserId = NewType('UserId', int)

# Fails at runtime and does not typecheck
class AdminUserId(UserId): pass

然而,我們可以在 "派生的" NewType 的基礎(chǔ)上創(chuàng)建一個(gè) NewType

from typing import NewType

UserId = NewType('UserId', int)

ProUserId = NewType('ProUserId', UserId)

并且 ProUserId 的類型檢查將按預(yù)期工作。

有關(guān)更多詳細(xì)信息,請(qǐng)參閱 PEP 484

注解

回想一下,使用類型別名聲明兩種類型彼此 等效Alias = Original 將使靜態(tài)類型檢查對(duì)待所有情況下 Alias 完全等同于 Original。當(dāng)您想簡(jiǎn)化復(fù)雜類型簽名時(shí),這很有用。

相反,NewType 聲明一種類型是另一種類型的子類型。Derived = NewType('Derived', Original) 將使靜態(tài)類型檢查器將 Derived 當(dāng)作 Original子類 ,這意味著 Original 類型的值不能用于 Derived 類型的值需要的地方。當(dāng)您想以最小的運(yùn)行時(shí)間成本防止邏輯錯(cuò)誤時(shí),這非常有用。

3.5.2 新版功能.

Callable?

期望特定簽名的回調(diào)函數(shù)的框架可以將類型標(biāo)注為 Callable[[Arg1Type, Arg2Type], ReturnType]

例如

from typing import Callable

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

def async_query(on_success: Callable[[int], None],
                on_error: Callable[[int, Exception], None]) -> None:
    # Body

通過用文字省略號(hào)替換類型提示中的參數(shù)列表: Callable[...,ReturnType],可以聲明可調(diào)用的返回類型,而無需指定調(diào)用簽名。

泛型(Generic)?

由于無法以通用方式靜態(tài)推斷有關(guān)保存在容器中的對(duì)象的類型信息,因此抽象基類已擴(kuò)展為支持訂閱以表示容器元素的預(yù)期類型。

from typing import Mapping, Sequence

def notify_by_email(employees: Sequence[Employee],
                    overrides: Mapping[str, str]) -> None: ...

泛型可以通過使用typing模塊中名為 TypeVar 的新工廠進(jìn)行參數(shù)化。

from typing import Sequence, TypeVar

T = TypeVar('T')      # Declare type variable

def first(l: Sequence[T]) -> T:   # Generic function
    return l[0]

用戶定義的泛型類型?

用戶定義的類可以定義為泛型類。

from typing import TypeVar, Generic
from logging import Logger

T = TypeVar('T')

class LoggedVar(Generic[T]):
    def __init__(self, value: T, name: str, logger: Logger) -> None:
        self.name = name
        self.logger = logger
        self.value = value

    def set(self, new: T) -> None:
        self.log('Set ' + repr(self.value))
        self.value = new

    def get(self) -> T:
        self.log('Get ' + repr(self.value))
        return self.value

    def log(self, message: str) -> None:
        self.logger.info('%s: %s', self.name, message)

Generic[T] 作為基類定義了類 LoggedVar 采用單個(gè)類型參數(shù) T。這也使得 T 作為類體內(nèi)的一個(gè)類型有效。

Generic 基類定義了 __class_getitem__() ,使得 LoggedVar[t] 作為類型有效:

from typing import Iterable

def zero_all_vars(vars: Iterable[LoggedVar[int]]) -> None:
    for var in vars:
        var.set(0)

泛型類型可以有任意數(shù)量的類型變量,并且類型變量可能會(huì)受到限制:

from typing import TypeVar, Generic
...

T = TypeVar('T')
S = TypeVar('S', int, str)

class StrangePair(Generic[T, S]):
    ...

Generic 每個(gè)參數(shù)的類型變量必須是不同的。這是無效的:

from typing import TypeVar, Generic
...

T = TypeVar('T')

class Pair(Generic[T, T]):   # INVALID
    ...

您可以對(duì) Generic 使用多重繼承:

from typing import TypeVar, Generic, Sized

T = TypeVar('T')

class LinkedList(Sized, Generic[T]):
    ...

從泛型類繼承時(shí),某些類型變量可能是固定的:

from typing import TypeVar, Mapping

T = TypeVar('T')

class MyDict(Mapping[str, T]):
    ...

在這種情況下,MyDict 只有一個(gè)參數(shù),T

在不指定類型參數(shù)的情況下使用泛型類別會(huì)為每個(gè)位置假設(shè) Any。在下面的例子中,MyIterable 不是泛型,但是隱式繼承自 Iterable[Any]:

from typing import Iterable

class MyIterable(Iterable): # Same as Iterable[Any]

用戶定義的通用類型別名也受支持。例子:

from typing import TypeVar, Iterable, Tuple, Union
S = TypeVar('S')
Response = Union[Iterable[S], int]

# Return type here is same as Union[Iterable[str], int]
def response(query: str) -> Response[str]:
    ...

T = TypeVar('T', int, float, complex)
Vec = Iterable[Tuple[T, T]]

def inproduct(v: Vec[T]) -> T: # Same as Iterable[Tuple[T, T]]
    return sum(x*y for x, y in v)

在 3.7 版更改: Generic 不再擁有一個(gè)自定義的元類。

一個(gè)用戶定義的泛型類能夠使用抽象基本類作為基類,而不會(huì)發(fā)生元類沖突。泛型元類不再被支持。參數(shù)化泛型的結(jié)果會(huì)被緩存,并且在 typing 模塊中的大部分類型是可哈希且可比較相等性的。

Any 類型?

Any 是一種特殊的類型。靜態(tài)類型檢查器將所有類型視為與 Any 兼容,反之亦然, Any 也與所有類型相兼容。

這意味著可對(duì)類型為 Any 的值執(zhí)行任何操作或方法調(diào)用,并將其賦值給任何變量:

from typing import Any

a = None    # type: Any
a = []      # OK
a = 2       # OK

s = ''      # type: str
s = a       # OK

def foo(item: Any) -> int:
    # Typechecks; 'item' could be any type,
    # and that type might have a 'bar' method
    item.bar()
    ...

需要注意的是,將 Any 類型的值賦值給另一個(gè)更具體的類型時(shí),Python不會(huì)執(zhí)行類型檢查。例如,當(dāng)把 a 賦值給 s 時(shí),即使 s 被聲明為 str 類型,在運(yùn)行時(shí)接收到的是 int 值,靜態(tài)類型檢查器也不會(huì)報(bào)錯(cuò)。

此外,所有返回值無類型或形參無類型的函數(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)需要混用動(dòng)態(tài)類型和靜態(tài)類型的代碼時(shí),上述行為可以讓 Any 被用作 應(yīng)急出口

Anyobject 的行為對(duì)比。與 Any 相似,所有的類型都是 object 的子類型。然而不同于 Any,反之并不成立: object 不是 其他所有類型的子類型。

這意味著當(dāng)一個(gè)值的類型是 object 的時(shí)候,類型檢查器會(huì)拒絕對(duì)它的幾乎所有的操作。把它賦值給一個(gè)指定了類型的變量(或者當(dāng)作返回值)是一個(gè)類型錯(cuò)誤。比如說:

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 示意一個(gè)值可以類型安全地兼容任何類型。使用 Any 示意一個(gè)值地類型是動(dòng)態(tài)定義的。

類,函數(shù)和修飾器.?

這個(gè)模塊定義了如下的類,模塊和修飾器.

class typing.TypeVar?

類型變量

用法:

T = TypeVar('T')  # Can be anything
A = TypeVar('A', str, bytes)  # Must be str or bytes

Type variables exist primarily for the benefit of static type checkers. They serve as the parameters for generic types as well as for generic function definitions. See class Generic for more information on generic types. Generic functions work as follows:

def repeat(x: T, n: int) -> Sequence[T]:
    """Return a list containing n references to x."""
    return [x]*n

def longest(x: A, y: A) -> A:
    """Return the longest of two strings."""
    return x if len(x) >= len(y) else y

本質(zhì)上,后例的簽名重載了 (str, str) -> str(bytes, bytes) -> bytes。注意,參數(shù)是 str 子類的實(shí)例時(shí),返回類型仍是純 str

isinstance(x, T) 會(huì)在運(yùn)行時(shí)拋出 TypeError 異常。一般地說, isinstance()issubclass() 不應(yīng)該和類型一起使用。

通過 covariant=Truecontravariant=True 可以把類型變量標(biāo)記為協(xié)變量或逆變量。詳見 PEP 484。默認(rèn)情況下,類型變量是不變量。類型變量還可以用 bound=<type> 指定上限。這里的意思是,(顯式或隱式地)取代類型變量的實(shí)際類型必須是限定類型的子類,詳見 PEP 484

class typing.Generic?

用于泛型類型的抽象基類。

泛型類型一般通過繼承含一個(gè)或多個(gè)類型變量的類實(shí)例進(jìn)行聲明。例如,泛型映射類型定義如下:

class Mapping(Generic[KT, VT]):
    def __getitem__(self, key: KT) -> VT:
        ...
        # Etc.

這個(gè)類之后可以被這樣用:

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.Type(Generic[CT_co])?

一個(gè)注解為 C 的變量可以接受一個(gè)類型為 C 的值。相對(duì)地,一個(gè)注解為 Type[C] 的變量可以接受本身為類的值 —— 更精確地說它接受 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()

?Type[C] 是協(xié)變的這一事實(shí)暗示了任何 C 的子類應(yīng)當(dāng)實(shí)現(xiàn)與 C 相同的構(gòu)造器簽名和類方法簽名。類型檢查器應(yīng)當(dāng)標(biāo)記違反的情況,但應(yīng)當(dāng)也允許子類中調(diào)用構(gòu)造器符合指示的基類。類型檢查器被要求如何處理這種情況可能會(huì)在 PEP 484 將來的版本中改變。

?Type 合法的參數(shù)僅有類、 Any類型變量 以及上述類型的聯(lián)合類型。例如:

def new_non_team_user(user_class: Type[Union[BaseUser, ProUser]]): ...

?Type[Any] 等價(jià)于 Type,因此繼而等價(jià)于 type,它是 Python 的元類層級(jí)的根部。

3.5.2 新版功能.

class typing.Iterable(Generic[T_co])?

collections.abc.Iterable 的泛型版本。

class typing.Iterator(Iterable[T_co])?

collections.abc.Iterator 的泛型版本。

class typing.Reversible(Iterable[T_co])?

collections.abc.Reversible 的泛型版本。

class typing.SupportsInt?

含抽象方法 __int__ 的抽象基類。

class typing.SupportsFloat?

含抽象方法 __float__ 的抽象基類。

class typing.SupportsComplex?

含抽象方法 __complex__ 的抽象基類。

class typing.SupportsBytes?

含抽象方法 __bytes__ 的抽象基類(ABC)

class typing.SupportsAbs?

含抽象方法 __abs__ 的抽象基類(ABC)是其返回類型里的協(xié)變量。

class typing.SupportsRound?

含抽象方法 __round__ 的抽象基類,是其返回類型的協(xié)變量。

class typing.Container(Generic[T_co])?

collections.abc.Container 的泛型版本。

class typing.Hashable?

collections.abc.Hashable 的別名。

class typing.Sized?

collections.abc.Sized 的別名。

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

collections.abc.Collection 的泛型版本。

3.6.0 新版功能.

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

collections.abc.Set 的泛型版本。

class typing.MutableSet(AbstractSet[T])?

collections.abc.MutableSet 的泛型版本。

class typing.Mapping(Sized, Collection[KT], Generic[VT_co])?

collections.abc.Mapping 的泛型版本。這個(gè)類型可以如下使用:

def get_position_in_index(word_list: Mapping[str, int], word: str) -> int:
    return word_list[word]
class typing.MutableMapping(Mapping[KT, VT])?

collections.abc.MutableMapping 的泛型版本。

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

collections.abc.Sequence 的泛型版本。

class typing.MutableSequence(Sequence[T])?

collections.abc.MutableSequence 的泛型版本。

class typing.ByteString(Sequence[int])?

collections.abc.ByteString 的泛型版本。

This type represents the types bytes, bytearray, and memoryview.

作為該類型的簡(jiǎn)稱,bytes 可用于標(biāo)注上述任意類型的參數(shù)。

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

collections.deque 的泛型版本。

3.5.4 新版功能.

3.6.1 新版功能.

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

list 的泛型版本。適用于注解返回類型。注解參數(shù)時(shí),最好使用 SequenceIterable 等抽象容器類型。

這個(gè)類型可以這樣用:

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]
class typing.Set(set, MutableSet[T])?

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

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

builtins.frozenset 的泛型版本。

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

collections.abc.MappingView 的泛型版本。

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

collections.abc.KeysView 的泛型版本。

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

collections.abc.ItemsView 的泛型版本。

class typing.ValuesView(MappingView[VT_co])?

collections.abc.ValuesView 的泛型版本。

class typing.Awaitable(Generic[T_co])?

collections.abc.Awaitable 的泛型版本。

3.5.2 新版功能.

class typing.Coroutine(Awaitable[V_co], Generic[T_co T_contra, V_co])?

collections.abc.Coroutine 的泛型版本。類型變量的的差異和順序與 Generator 的內(nèi)容相對(duì)應(yīng),例如:

from typing import List, Coroutine
c = None # type: Coroutine[List[str], str, int]
...
x = c.send('hi') # type: List[str]
async def bar() -> None:
    x = await c # type: int

3.5.3 新版功能.

class typing.AsyncIterable(Generic[T_co])?

collections.abc.AsyncIterable 的泛型版本。

3.5.2 新版功能.

class typing.AsyncIterator(AsyncIterable[T_co])?

collections.abc.AsyncIterator 的泛型版本。

3.5.2 新版功能.

class typing.ContextManager(Generic[T_co])?

contextlib.AbstractContextManager 的泛型版本。

3.5.4 新版功能.

3.6.0 新版功能.

class typing.AsyncContextManager(Generic[T_co])?

contextlib.AbstractAsyncContextManager 的泛型版本。

3.5.4 新版功能.

3.6.2 新版功能.

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

dict 的泛型版本。對(duì)標(biāo)注返回類型比較有用。如果要標(biāo)注參數(shù)的話,使用如 Mapping 的抽象容器類型是更好的選擇。

這個(gè)類型可以這樣使用:

def count_words(text: str) -> Dict[str, int]:
    ...
class typing.DefaultDict(collections.defaultdict, MutableMapping[KT, VT])?

collections.defaultdict 的泛型版本。

3.5.2 新版功能.

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

collections.OrderedDict 的泛型版本。

3.7.2 新版功能.

class typing.Counter(collections.Counter, Dict[T, int])?

collections.Counter 的泛型版本。

3.5.4 新版功能.

3.6.1 新版功能.

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

collections.ChainMap 的泛型版本。

3.5.4 新版功能.

3.6.1 新版功能.

class typing.Generator(Iterator[T_co], Generic[T_co, T_contra, V_co])?

生成器可以由泛型類型 Generator[YieldType, SendType, ReturnType] 注解。例如:

def echo_round() -> Generator[int, float, str]:
    sent = yield 0
    while sent >= 0:
        sent = yield round(sent)
    return 'Done'

注意,與 typing 模塊里的其他泛型不同, Generator 的``SendType`` 的操作是逆變的, 不是協(xié)變,也是不變。

如果生成器只生成值,可將 SendTypeReturnType 設(shè)為 None

def infinite_stream(start: int) -> Generator[int, None, None]:
    while True:
        yield start
        start += 1

另外,把生成器注解為返回類型

def infinite_stream(start: int) -> Iterator[int]:
    while True:
        yield start
        start += 1
class typing.AsyncGenerator(AsyncIterator[T_co], Generic[T_co, T_contra])?

異步生成器可由泛型類型 AsyncGenerator[YieldType, SendType] 注解。例如:

async def echo_round() -> AsyncGenerator[int, float]:
    sent = yield 0
    while sent >= 0.0:
        rounded = await round(sent)
        sent = yield rounded

與常規(guī)生成器不同,異步生成器不能返回值,因此沒有 ReturnType 類型參數(shù)。 與 Generator 類似,SendType 也屬于逆變行為。

如果生成器只產(chǎn)生值,可將 SendType 設(shè)置為 None

async def infinite_stream(start: int) -> AsyncGenerator[int, None]:
    while True:
        yield start
        start = await increment(start)

此外,可用 AsyncIterable[YieldType]AsyncIterator[YieldType] 注解生成器的類型:

async def infinite_stream(start: int) -> AsyncIterator[int]:
    while True:
        yield start
        start = await increment(start)

3.6.1 新版功能.

class typing.Text?

Textstr 的別名。提供了對(duì) Python 2 代碼的向下兼容:Python 2 中,Text 是``unicode`` 的別名。

def add_unicode_checkmark(text: Text) -> Text:
    return text + u' \u2713'

3.5.2 新版功能.

class typing.IO?
class typing.TextIO?
class typing.BinaryIO?

泛型類型 IO[AnyStr] 及其子類 TextIO(IO[str])BinaryIO(IO[bytes]) 表示 I/O 流的類型,例如 open() 所返回的對(duì)象。

class typing.Pattern?
class typing.Match?

這些類型對(duì)應(yīng)的是從 re.compile()re.match() 返回的類型。 這些類型(及相應(yīng)的函數(shù))是 AnyStr 中的泛型并可通過編寫 Pattern[str], Pattern[bytes], Match[str]Match[bytes] 來具體指定。

class typing.NamedTuple?

collections.namedtuple() 的類型版本。

用法:

class Employee(NamedTuple):
    name: str
    id: int

這相當(dāng)于:

Employee = collections.namedtuple('Employee', ['name', 'id'])

為字段提供默認(rèn)值,要在類體內(nèi)賦值:

class Employee(NamedTuple):
    name: str
    id: int = 3

employee = Employee('Guido')
assert employee.id == 3

帶默認(rèn)值的字段必須在不帶默認(rèn)值的字段后面。

The resulting class has two extra attributes: _field_types, giving a dict mapping field names to types, and _field_defaults, a dict mapping field names to default values. (The field names are in the _fields attribute, which is part of the namedtuple API.)

NamedTuple 子類也支持文檔字符串與方法:

class Employee(NamedTuple):
    """Represents an employee."""
    name: str
    id: int = 3

    def __repr__(self) -> str:
        return f'<Employee {self.name}, id={self.id}>'

反向兼容用法:

Employee = NamedTuple('Employee', [('name', str), ('id', int)])

在 3.6 版更改: 添加了對(duì) PEP 526 中變量注解句法的支持。

在 3.6.1 版更改: 添加了對(duì)默認(rèn)值、方法、文檔字符串的支持。

class typing.ForwardRef?

用于字符串前向引用的內(nèi)部類型表示的類。 例如,List["SomeClass"] 會(huì)被隱式轉(zhuǎn)換為 List[ForwardRef("SomeClass")]。 這個(gè)類不應(yīng)由用戶來實(shí)例化,但可以由內(nèi)省工具使用。

typing.NewType(typ)?

A helper function to indicate a distinct types to a typechecker, see NewType. At runtime it returns a function that returns its argument. Usage:

UserId = NewType('UserId', int)
first_user = UserId(1)

3.5.2 新版功能.

typing.cast(typ, val)?

把值強(qiáng)制轉(zhuǎn)換為類型。

不變更返回值。對(duì)類型檢查器來說,這代表了返回值具有指定的類型,但在運(yùn)行時(shí),故意不做任何檢查(目的是讓該檢查速度盡量快)。

typing.get_type_hints(obj[, globals[, locals]])?

返回一個(gè)字典,字典內(nèi)含有函數(shù)、方法、模塊或類對(duì)象的類型提示。

一般情況下,與 obj.__annotations__ 相同。此外,可通過在 globalslocals 命名空間里進(jìn)行評(píng)估,以此來處理編碼為字符串字面量的前向引用。如有需要,在默認(rèn)值設(shè)置為 None``時(shí),可為函數(shù)或方法注解添加 ``Optional[t]。對(duì)于類 C,則返回一個(gè)由所有 __annotations__C.__mro__ 逆序合并而成的字典。

@typing.overload?

@overload 裝飾器可以修飾支持多個(gè)不同參數(shù)類型組合的函數(shù)或方法。@overload - 裝飾定義的系列必須緊跟一個(gè)非 @overload-裝飾定義(用于同一個(gè)函數(shù)/方法)。@overload-裝飾定義僅是為了協(xié)助類型檢查器, 因?yàn)樵撗b飾器會(huì)被非 @overload-裝飾定義覆蓋,后者用于運(yùn)行時(shí),而且會(huì)被類型檢查器忽略。在運(yùn)行時(shí)直接調(diào)用 @overload 裝飾的函數(shù)會(huì)觸發(fā) NotImplementedError。下面的重載示例給出了比聯(lián)合類型或類型變量更精準(zhǔn)的類型:

@overload
def process(response: None) -> None:
    ...
@overload
def process(response: int) -> Tuple[int, str]:
    ...
@overload
def process(response: bytes) -> str:
    ...
def process(response):
    <actual implementation>

詳見 PEP 484,與其他類型語義進(jìn)行對(duì)比。

@typing.no_type_check?

用于指明標(biāo)注不是類型提示的裝飾器。

decorator 裝飾器生效于類或函數(shù)上。如果作用于類上的話,它會(huì)遞歸地作用于這個(gè)類的所定義的所有方法上(但是對(duì)于超類或子類所定義的方法不會(huì)生效)。

此方法會(huì)就地地修改函數(shù)。

@typing.no_type_check_decorator?

使其它裝飾器起到 no_type_check() 效果的裝飾器。

本裝飾器用 no_type_check() 里的裝飾函數(shù)打包其他裝飾器。

@typing.type_check_only?

標(biāo)記一個(gè)類或函數(shù)在運(yùn)行時(shí)內(nèi)不可用的裝飾器。

在運(yùn)行時(shí),該裝飾器本身不可用。實(shí)現(xiàn)返回了私有類實(shí)例時(shí),它主要是用于標(biāo)記在類型存根文件中定義的類。

@type_check_only
class Response:  # private or not available at runtime
    code: int
    def get_header(self, name: str) -> str: ...

def fetch_response() -> Response: ...

注意,不建議返回私有類的實(shí)例,最好將這些類設(shè)為公共類。

typing.Any?

特殊類型,表明類型沒有任何限制。

  • 每一個(gè)類型都對(duì) Any 兼容。

  • Any 對(duì)每一個(gè)類型都兼容。

typing.NoReturn?

標(biāo)記一個(gè)函數(shù)沒有返回值的特殊類型。比如說:

from typing import NoReturn

def stop() -> NoReturn:
    raise RuntimeError('no way')

3.5.4 新版功能.

3.6.2 新版功能.

typing.Union?

聯(lián)合類型; Union[X, Y] 意味著:要不是 X,要不是 Y。

使用形如 Union[int, str] 的形式來定義一個(gè)聯(lián)合類型。細(xì)節(jié)如下:

  • 參數(shù)必須是類型,而且必須至少有一個(gè)參數(shù)。

  • 聯(lián)合類型的聯(lián)合類型會(huì)被展開打平,比如:

    Union[Union[int, str], float] == Union[int, str, float]
    
  • 僅有一個(gè)參數(shù)的聯(lián)合類型會(huì)坍縮成參數(shù)自身,比如:

    Union[int] == int  # The constructor actually returns int
    
  • 多余的參數(shù)會(huì)被跳過,比如:

    Union[int, str, int] == Union[int, str]
    
  • 在比較聯(lián)合類型的時(shí)候,參數(shù)順序會(huì)被忽略,比如:

    Union[int, str] == Union[str, int]
    
  • 你不能繼承或者實(shí)例化一個(gè)聯(lián)合類型。

  • 你不能寫成 Union[X][Y]

  • 你可以使用 Optional[X] 作為 Union[X, None] 的縮寫。

在 3.7 版更改: 不要在運(yùn)行時(shí)內(nèi)從聯(lián)合類型中移除顯式說明的子類。

typing.Optional?

可選類型。

?Optional[X] 等價(jià)于 Union[X, None]

請(qǐng)注意,這與可選參數(shù)并非相同的概念。可選參數(shù)是一個(gè)具有默認(rèn)值的參數(shù)。可選參數(shù)的類型注解并不因?yàn)樗强蛇x的就需要 Optional 限定符。例如:

def foo(arg: int = 0) -> None:
    ...

另一方面,如果允許顯式地傳遞值 None , 使用 Optional 也是正當(dāng)?shù)模瑹o論該參數(shù)是否是可選的。例如:

def foo(arg: Optional[int] = None) -> None:
    ...
typing.Tuple?

元組類型; Tuple[X, Y] 標(biāo)注了一個(gè)二元組類型,其第一個(gè)元素的類型為 X 且第二個(gè)元素的類型為 Y。空元組的類型可寫作 Tuple[()]

舉例: Tuple[T1, T2] 是一個(gè)二元組,類型分別為 T1 和 T2。 Tuple[int, float, str] 是一個(gè)由整數(shù)、浮點(diǎn)數(shù)和字符串組成的三元組。

為表達(dá)一個(gè)同類型元素的變長(zhǎng)元組,使用省略號(hào)字面量,如 Tuple[int, ...] 。單獨(dú)的一個(gè) Tuple 等價(jià)于 Tuple[Any, ...],進(jìn)而等價(jià)于 tuple

typing.Callable?

可調(diào)用類型; Callable[[int], str] 是一個(gè)函數(shù),接受一個(gè) int 參數(shù),返回一個(gè) str 。

下標(biāo)值的語法必須恰為兩個(gè)值:參數(shù)列表和返回類型。參數(shù)列表必須是一個(gè)類型和省略號(hào)組成的列表;返回值必須是單一一個(gè)類型。

不存在語法來表示可選的或關(guān)鍵詞參數(shù),這類函數(shù)類型罕見用于回調(diào)函數(shù)。 Callable[..., ReturnType] (使用字面省略號(hào))能被用于提示一個(gè)可調(diào)用對(duì)象,接受任意數(shù)量的參數(shù)并且返回 ReturnType。單獨(dú)的 Callable 等價(jià)于 Callable[..., Any] ,并且進(jìn)而等價(jià)于 collections.abc.Callable

typing.ClassVar?

特殊的類型構(gòu)造器,用以標(biāo)記類變量。

PEP 526 中被引入,ClassVar 包裹起來的變量注解指示了給定屬性預(yù)期用于類變量,并且不應(yīng)在類的實(shí)例上被設(shè)置。用法:

class Starship:
    stats: ClassVar[Dict[str, int]] = {} # class variable
    damage: int = 10                     # instance variable

ClassVar 僅接受類型,并且不能被再次下標(biāo)。

ClassVar 本身并不是一個(gè)類,并且不應(yīng)與 isinstance() or issubclass() 一起使用。 ClassVar 并不改變 Python 運(yùn)行時(shí)行為,但它可以被用于第三方類型檢查器。例如,某個(gè)類型檢查器可能會(huì)標(biāo)記以下代碼為錯(cuò)誤的:

enterprise_d = Starship(3000)
enterprise_d.stats = {} # Error, setting class variable on instance
Starship.stats = {}     # This is OK

3.5.3 新版功能.

typing.AnyStr?

AnyStr 類型變量的定義為 AnyStr = TypeVar('AnyStr', str, bytes)

這里指的是,它可以接受任意同類字符串,但不支持混用不同類別的字符串。例如:

def concat(a: AnyStr, b: AnyStr) -> AnyStr:
    return a + b

concat(u"foo", u"bar")  # Ok, output has type 'unicode'
concat(b"foo", b"bar")  # Ok, output has type 'bytes'
concat(u"foo", b"bar")  # Error, cannot mix unicode and bytes
typing.TYPE_CHECKING?

被第三方靜態(tài)類型檢查器假定為 True 的特殊常量。 在運(yùn)行時(shí)為 False。 用法如下:

if TYPE_CHECKING:
    import expensive_mod

def fun(arg: 'expensive_mod.SomeType') -> None:
    local_var: expensive_mod.AnotherType = other_fun()

Note that the first type annotation must be enclosed in quotes, making it a "forward reference", to hide the expensive_mod reference from the interpreter runtime. Type annotations for local variables are not evaluated, so the second annotation does not need to be enclosed in quotes.

3.5.2 新版功能.