26.1. 键入 — 支持类型提示 — Python 文档

来自菜鸟教程
Python/docs/3.6/library/typing
跳转至:导航、​搜索

26.1. 打字 — 支持类型提示

3.5 版中的新功能。


源代码: :source:`Lib/typing.py`

笔记

打字模块已在 临时基础上 包含在标准库中。 如果核心开发人员认为有必要,可能会添加新功能,即使在次要版本之间,API 也可能会更改。



该模块支持 PEP 484PEP 526 指定的类型提示。 最基本的支持包括 AnyUnionTupleCallableTypeVar 和 [ X138X]通用。 有关完整规格,请参阅 PEP 484。 有关类型提示的简化介绍,请参阅 PEP 483

下面的函数接受并返回一个字符串,注释如下:

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

在函数 greeting 中,参数 name 的类型应为 str,返回类型为 str。 子类型被接受为参数。

26.1.1. 类型别名

类型别名是通过将类型分配给别名来定义的。 在本例中,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])

类型别名对于简化复杂的类型签名很有用。 例如:

from typing import Dict, Tuple, List

ConnectionOptions = Dict[str, str]
Address = Tuple[str, int]
Server = Tuple[Address, ConnectionOptions]

def broadcast_message(message: str, servers: List[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: List[Tuple[Tuple[str, int], Dict[str, str]]]) -> None:
    ...

请注意,作为类型提示的 None 是一种特殊情况,并由 type(None) 替换。


26.1.2. 新类型

使用 NewType() 辅助函数创建不同的类型:

from typing import NewType

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

静态类型检查器会将新类型视为原始类型的子类。 这有助于捕获逻辑错误:

def get_user_name(user_id: UserId) -> str:
    ...

# typechecks
user_a = get_user_name(UserId(42351))

# does not typecheck; an int is not a UserId
user_b = get_user_name(-1)

您仍然可以对 UserId 类型的变量执行所有 int 操作,但结果将始终为 int 类型。 这使您可以在可能需要 int 的任何地方传入 UserId,但会防止您以无效的方式意外创建 UserId

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

请注意,这些检查仅由静态类型检查器强制执行。 在运行时,语句 Derived = NewType('Derived', Base) 将使 Derived 成为立即返回您传递给它的任何参数的函数。 这意味着表达式 Derived(some_value) 不会创建新类或引入任何超出常规函数调用的开销。

更准确地说,表达式 some_value is Derived(some_value) 在运行时始终为真。

这也意味着无法创建 Derived 的子类型,因为它是运行时的标识函数,而不是实际类型:

from typing import NewType

UserId = NewType('UserId', int)

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

但是,可以基于“派生”NewType 创建 NewType()

from typing import NewType

UserId = NewType('UserId', int)

ProUserId = NewType('ProUserId', UserId)

ProUserId 的类型检查将按预期工作。

有关更多详细信息,请参阅 PEP 484

笔记

回想一下,类型别名的使用将两种类型声明为彼此 等价 。 执行 Alias = Original 将使静态类型检查器在所有情况下将 Alias 视为 Original 完全等效的 。 当您想要简化复杂的类型签名时,这很有用。

相反, NewType 将一种类型声明为另一种类型的 子类型 。 执行 Derived = NewType('Derived', Original) 将使静态类型检查器将 Derived 视为 Original子类 ,这意味着 Original 类型的值不能用于需要 Derived 类型值的地方。 当您希望以最小的运行成本防止逻辑错误时,这很有用。


版本 3.5.2 中的新功能。


26.1.3. 可调用

需要特定签名的回调函数的框架可能会使用 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

通过用文字省略号替换类型提示中的参数列表,可以在不指定调用签名的情况下声明可调用的返回类型:Callable[..., ReturnType]


26.1.4. 泛型

由于容器中保存的对象的类型信息不能以通用方式静态推断,抽象基类已被扩展以支持订阅以表示容器元素的预期类型。

from typing import Mapping, Sequence

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

泛型可以通过使用称为 TypeVar 的新工厂进行参数化。

from typing import Sequence, TypeVar

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

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

26.1.5. 用户定义的泛型类型

用户定义的类可以定义为泛型类。

from typing import TypeVar, Generic
from logging import Logger

T = TypeVar('T')

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

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

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

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

Generic[T] 作为基类定义了类 LoggedVar 采用单个类型参数 T 。 这也使 T 作为类体内的类型有效。

Generic 基类使用定义 __getitem__() 的元类,以便 LoggedVar[t] 作为类型有效:

from typing import Iterable

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

泛型类型可以有任意数量的类型变量,并且类型变量可能受到约束:

from typing import TypeVar, Generic
...

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

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

Generic 的每个类型变量参数必须是不同的。 因此这是无效的:

from typing import TypeVar, Generic
...

T = TypeVar('T')

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

您可以将多重继承与 Generic 一起使用:

from typing import TypeVar, Generic, Sized

T = TypeVar('T')

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

从泛型类继承时,可以修复一些类型变量:

from typing import TypeVar, Mapping

T = TypeVar('T')

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

在这种情况下,MyDict 有一个参数,T

使用不指定类型参数的泛型类假定每个位置为 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)

Generic 使用的元类是 abc.ABCMeta 的子类。 泛型类可以通过包含抽象方法或属性成为 ABC,泛型类也可以将 ABC 作为基类,而不会发生元类冲突。 不支持通用元类。 参数化泛型的结果会被缓存,并且typing 模块中的大多数类型都是可散列的并且可以比较相等。


26.1.6. 这任何类型

一种特殊的类型是 Any。 静态类型检查器会将每种类型视为与 Any 兼容,将 Any 视为与每种类型兼容。

这意味着可以对 Any 上的类型值执行任何操作或方法调用并将其分配给任何变量:

from typing import Any

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

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

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

请注意,将 Any 类型的值分配给更精确的类型时,不会执行类型检查。 例如,静态类型检查器在将 a 分配给 s 时没有报告错误,即使 s 被声明为类型 str 并接收运行时的 int 值!

此外,所有没有返回类型或参数类型的函数将隐式默认使用 Any

def legacy_parser(text):
    ...
    return data

# A static type checker will treat the above
# as having the same signature as:
def legacy_parser(text: Any) -> Any:
    ...
    return data

当您需要混合动态和静态类型代码时,此行为允许将 Any 用作 逃生舱口

Any 的行为与 object 的行为进行对比。 类似于 Any,每个类型都是 object 的子类型。 然而,与 Any 不同的是,反过来就不成立了:objectnot 所有其他类型的子类型。

这意味着当值的类型是 object 时,类型检查器将拒绝对其进行几乎所有操作,并将其分配给更特殊类型的变量(或将其用作返回值)是一个类型错误。 例如:

def hash_a(item: object) -> int:
    # Fails; an object does not have a 'magic' method.
    item.magic()
    ...

def hash_b(item: Any) -> int:
    # Typechecks
    item.magic()
    ...

# Typechecks, since ints and strs are subclasses of object
hash_a(42)
hash_a("foo")

# Typechecks, since Any is compatible with all types
hash_b(42)
hash_b("foo")

使用 object 指示值可以是类型安全的任何类型。 使用 Any 表示一个值是动态类型的。


26.1.7. 类、函数和装饰器

该模块定义了以下类、函数和装饰器:

class typing.TypeVar

类型变量。

用法:

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

类型变量的存在主要是为了静态类型检查器的好处。 它们用作泛型类型以及泛型函数定义的参数。 有关泛型类型的更多信息,请参阅类 Generic。 通用函数的工作方式如下:

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

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

后一个例子的签名本质上是(str, str) -> str(bytes, bytes) -> bytes的重载。 还要注意,如果参数是 str 的某个子类的实例,返回类型仍然是普通的 str

在运行时,isinstance(x, T) 将引发 TypeError。 通常, isinstance()issubclass() 不应与类型一起使用。

类型变量可以通过传递 covariant=Truecontravariant=True 来标记协变或逆变。 有关更多详细信息,请参阅 PEP 484。 默认情况下,类型变量是不变的。 或者,类型变量可以使用 bound=<type> 指定上限。 这意味着替换(显式或隐式)类型变量的实际类型必须是边界类型的子类,请参阅 PEP 484

class typing.Generic

泛型类型的抽象基类。

泛型类型通常通过从具有一个或多个类型变量的此类的实例化继承来声明。 例如,通用映射类型可能定义为:

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

然后可以按如下方式使用此类:

X = TypeVar('X')
Y = TypeVar('Y')

def lookup_name(mapping: Mapping[X, Y], key: X, default: Y) -> Y:
    try:
        return mapping[key]
    except KeyError:
        return default
class typing.Type(Generic[CT_co])

C 注释的变量可以接受类型为 C 的值。 相比之下,用 Type[C] 注释的变量可以接受类本身的值——具体来说,它将接受 C类对象 。 例如:

a = 3         # Has type 'int'
b = int       # Has type 'Type[int]'
c = type(a)   # Also has type 'Type[int]'

注意 Type[C] 是协变的:

class User: ...
class BasicUser(User): ...
class ProUser(User): ...
class TeamUser(User): ...

# Accepts User, BasicUser, ProUser, TeamUser, ...
def make_new_user(user_class: Type[User]) -> User:
    # ...
    return user_class()

Type[C] 是协变的这一事实意味着 C 的所有子类应该实现与 C 相同的构造函数签名和类方法签名。 类型检查器应该标记违反这一点,但也应该允许子类中的构造函数调用与指定基类中的构造函数调用相匹配。 在 PEP 484 的未来修订版中,类型检查器如何处理这种特殊情况可能会发生变化。

Type 的唯一合法参数是类、Any类型变量 和任何这些类型的联合。 例如:

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

Type[Any] 相当于 Type,后者又相当于 type,这是 Python 元类层次结构的根。

版本 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__ 的 ABC。
class typing.SupportsFloat
带有一个抽象方法 __float__ 的 ABC。
class typing.SupportsComplex
带有一个抽象方法 __complex__ 的 ABC。
class typing.SupportsBytes
带有一个抽象方法 __bytes__ 的 ABC。
class typing.SupportsAbs
带有一个抽象方法 __abs__ 的 ABC,它的返回类型是协变的。
class typing.SupportsRound
带有一个抽象方法 __round__ 的 ABC,它的返回类型是协变的。
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 版中的新功能。

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 的通用版本。
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 的通用版本。

此类型表示类型 bytesbytearraymemoryview

作为这种类型的简写,bytes 可用于注释上述任何类型的参数。

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

collections.deque 的通用版本。

版本 3.6.1 中的新功能。

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

list 的通用版本。 用于注释返回类型。 要注释参数,最好使用抽象集合类型,例如 MappingSequenceAbstractSet

这种类型可以如下使用:

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 的通用版本。
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 的通用版本。
class typing.Coroutine(Awaitable[V_co], Generic[T_co T_contra, V_co])

collections.abc.Coroutine 的通用版本。 类型变量的方差和顺序对应于Generator,例如:

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
class typing.AsyncIterable(Generic[T_co])
collections.abc.AsyncIterable 的通用版本。
class typing.AsyncIterator(AsyncIterable[T_co])
collections.abc.AsyncIterator 的通用版本。
class typing.ContextManager(Generic[T_co])

contextlib.AbstractContextManager 的通用版本。

3.6 版中的新功能。

class typing.AsyncContextManager(Generic[T_co])

具有异步抽象 __aenter__()__aexit__() 方法的 ABC。

3.6 版中的新功能。

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

dict 的通用版本。 该类型的用法如下:

def get_position_in_index(word_list: Dict[str, int], word: str) -> int:
    return word_list[word]
class typing.DefaultDict(collections.defaultdict, MutableMapping[KT, VT])

collections.defaultdict 的通用版本。

版本 3.5.2 中的新功能。

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

collections.Counter 的通用版本。

版本 3.6.1 中的新功能。

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

collections.ChainMap 的通用版本。

版本 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'

请注意,与类型模块中的许多其他泛型不同,GeneratorSendType 的行为是逆变的,而不是协变或不变的。

如果您的生成器只会产生值,请将 SendTypeReturnType 设置为 None

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

或者,将您的生成器注释为具有 Iterable[YieldType]Iterator[YieldType] 的返回类型:

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

异步生成器可以通过通用类型 AsyncGenerator[YieldType, SendType] 进行注释。 例如:

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

与普通生成器不同,异步生成器不能返回值,因此没有 ReturnType 类型参数。 与 Generator 一样,SendType 的行为也是逆变的。

如果您的生成器只会产生值,请将 SendType 设置为 None

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

或者,将您的生成器注释为具有 AsyncIterable[YieldType]AsyncIterator[YieldType] 的返回类型:

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

3.5.4 版中的新功能。

class typing.Text

Textstr 的别名。 提供它是为了为 Python 2 代码提供向前兼容的路径:在 Python 2 中,Textunicode 的别名。

使用 Text 指示值必须以与 Python 2 和 Python 3 兼容的方式包含 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() 返回。
class typing.Pattern

class typing.Match

这些类型别名对应于 re.compile()re.match() 的返回类型。 这些类型(和相应的函数)在 AnyStr 中是通用的,可以通过写 Pattern[str]Pattern[bytes]Match[str] 或 [ X147X]。
class typing.NamedTuple

namedtuple 的类型化版本。

用法:

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

这相当于:

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

要给一个字段一个默认值,你可以在类体中分配给它:

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

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

具有默认值的字段必须在任何没有默认值的字段之后。

生成的类有两个额外的属性:_field_types,给出一个将字段名称映射到类型的字典,以及 _field_defaults,一个将字段名称映射到默认值的字典。 (字段名称在 _fields 属性中,它是 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 版更改: 添加了对 PEP 526 变量注释语法的支持。

3.6.1 版更改: 添加了对默认值、方法和文档字符串的支持。

typing.NewType(typ)

用于向类型检查器指示不同类型的辅助函数,请参阅 NewType。 在运行时,它返回一个返回其参数的函数。 用法:

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

版本 3.5.2 中的新功能。

typing.cast(typ, val)

将值转换为类型。

这将返回不变的值。 对于类型检查器,这表明返回值具有指定的类型,但在运行时我们故意不检查任何东西(我们希望这尽可能快)。

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

返回一个包含函数、方法、模块或类对象的类型提示的字典。

这通常与 obj.__annotations__ 相同。 此外,编码为字符串文字的前向引用是通过在 globalslocals 命名空间中评估它们来处理的。 如有必要,如果设置了等于 None 的默认值,则为函数和方法注释添加 Optional[t]。 对于类 C,返回一个字典,该字典是通过将所有 __annotations__ 沿 C.__mro__ 以相反顺序合并而成的。

@typing.overload

@overload 装饰器允许描述支持多种不同参数类型组合的函数和方法。 一系列 @overload 修饰的定义必须紧跟一个非 @overload 修饰的定义(对于相同的函数/方法)。 @overload 修饰的定义仅对类型检查器有益,因为它们将被非 @overload 修饰的定义覆盖,而后者在运行时使用但应忽略通过类型检查器。 在运行时,直接调用 @overload 修饰的函数会引发 NotImplementedError。 提供比使用联合或类型变量表示的类型更精确的重载示例:

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

有关详细信息以及与其他类型语义的比较,请参阅 PEP 484

@typing.no_type_check

装饰器来指示注释不是类型提示。

这用作类或函数 装饰器 。 对于一个类,它递归地应用于该类中定义的所有方法(但不适用于其超类或子类中定义的方法)。

这会改变适当的功能。

@typing.no_type_check_decorator

装饰器给另一个装饰器 no_type_check() 效果。

这用将装饰函数包装在 no_type_check() 中的东西包装了装饰器。

typing.Any
表示无约束类型的特殊类型。
  • 每种类型都与 Any 兼容。
  • Any 兼容所有类型。
typing.NoReturn

指示函数永不返回的特殊类型。 例如:

from typing import NoReturn

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

3.6.5 版中的新功能。

typing.Union

联合类型; Union[X, Y] 表示 X 或 Y。

要定义联合,请使用例如 Union[int, str]。 细节:

  • 参数必须是类型,并且必须至少有一个。

  • 工会的工会被扁平化,例如:

    Union[Union[int, str], float] == Union[int, str, float]
  • 单个参数的联合消失,例如:

    Union[int] == int  # The constructor actually returns int
  • 跳过冗余参数,例如:

    Union[int, str, int] == Union[int, str]
  • 比较联合时,将忽略参数顺序,例如:

    Union[int, str] == Union[str, int]
  • 当一个类及其子类存在时,后者将被跳过,例如:

    Union[int, object] == object
  • 您不能子类化或实例化联合。

  • 你不能写Union[X][Y]

  • 您可以使用 Optional[X] 作为 Union[X, None] 的简写。

typing.Optional

可选类型。

Optional[X] 相当于 Union[X, None]

请注意,这与可选参数不同,后者具有默认值。 具有默认值的可选参数不需要 Optional 在其类型注释上的限定符,因为它是可选的。 例如:

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

另一方面,如果允许 None 的显式值,则使用 Optional 是合适的,无论参数是否可选。 例如:

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

元组类型; Tuple[X, Y] 是两个元素的元组类型,第一个元素是 X 类型,第二个元素是 Y 类型。

示例: Tuple[T1, T2] 是对应于类型变量 T1 和 T2 的两个元素的元组。 Tuple[int, float, str] 是一个 int、一个浮点数和一个字符串的元组。

要指定同构类型的可变长度元组,请使用文字省略号,例如 Tuple[int, ...]。 一个普通的 Tuple 等价于 Tuple[Any, ...],反过来又相当于 tuple

typing.Callable

可调用类型; Callable[[int], str] 是 (int) -> str 的函数。

订阅语法必须始终与两个值一起使用:参数列表和返回类型。 参数列表必须是类型列表或省略号; 返回类型必须是单一类型。

没有指示可选参数或关键字参数的语法; 此类函数类型很少用作回调类型。 Callable[..., ReturnType](字面省略号)可用于键入hint a callable 接受任意数量的参数并返回ReturnType。 一个普通的 Callable 等价于 Callable[..., Any],进而相当于 collections.abc.Callable

typing.ClassVar

用于标记类变量的特殊类型构造。

正如在 PEP 526 中所介绍的,ClassVar 中包装的变量注释表示给定的属性旨在用作类变量,不应在该类的实例上设置。 用法:

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

ClassVar 只接受类型,不能进一步订阅。

ClassVar 本身不是类,不应与 isinstance()issubclass() 一起使用。 ClassVar 不会改变 Python 运行时的行为,但它可以被第三方类型检查器使用。 例如,类型检查器可能会将以下代码标记为错误:

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

3.5.3 版中的新功能。

typing.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

第 3 方静态类型检查器假定为 True 的特殊常量。 运行时为 False。 用法:

if TYPE_CHECKING:
    import expensive_mod

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

请注意,第一个类型注释必须用引号括起来,使其成为“前向引用”,以从解释器运行时隐藏 expensive_mod 引用。 不评估局部变量的类型注释,因此不需要用引号将第二个注释括起来。

版本 3.5.2 中的新功能。