typing — Поддержка подсказок типа

Добавлено в версии 3.5.

Исходный код: Lib/typing.py

Примечание

Среда выполнения Python не применяет аннотации типов функций и переменных. Они могут использоваться сторонними инструментами, такими как средства проверки типов, IDE, линтеры и т. д.


Этот модуль обеспечивает во время выполнения поддержку подсказок типов, как указано в PEP 484, PEP 526, PEP 544, PEP 586, PEP 589 и PEP 591. Самая основная поддержка состоит из типов Any, Union, Tuple, Callable, TypeVar и Generic. Полную спецификацию см. в PEP 484. Для упрощённого знакомства с подсказками типов см. PEP 483.

Функция ниже принимает и возвращает строку и аннотируется следующим образом:

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

В функция greeting ожидается, что аргумент name будет иметь тип str и тип возвращаемого значения str. Подтипы принимаются в качестве аргументов.

Псевдонимы типа

Псевдоним типа определяется путём присвоения типа псевдониму. В этом примере Vector и List[float] будут рассматриваться как взаимозаменяемые синонимы:

from typing import List
Vector = List[float]

def scale(scalar: float, vector: Vector) -> Vector:
    return [scalar * num for num in vector]

# проверка типов; список флоатов квалифицируется как Vector.
new_vector = scale(2.0, [1.0, -4.2, 5.4])

Псевдонимы типов полезны для упрощёния сигнатур сложных типов. Например:

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

# Средство проверки статического типа будет рассматривать предыдущий тип сигнатуры
# как точный эквивалент этому типу.
def broadcast_message(
        message: str,
        servers: Sequence[Tuple[Tuple[str, int], Dict[str, str]]]) -> None:
    ...

Обратите внимание, что None в качестве подсказки типа является особым случаем и заменяется на type(None).

NewType

Использовать вспомогательную функцию NewType() для создания отдельных типов:

from typing import NewType

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

Средство проверки статического типа будет обрабатывать новый тип, как если бы он был подклассом исходного типа. Это полезно для выявления логических ошибок:

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

# проверки типа
user_a = get_user_name(UserId(42351))

# не проверяет тип; int не является UserId
user_b = get_user_name(-1)

Вы по-прежнему можете выполнять все операции int с переменной типа UserId, но результат всегда будет иметь тип int. Это позволяет передать UserId везде, где можно ожидать int, но предотвратит случайное создание UserId недопустимым способом:

# 'output' имеет тип 'int', а не '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)

# Сбой во время выполнения и не выполняет проверку типа
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.

Callable

Платформы, ожидающие функций обратного вызова для определенных сигнатур, могут использовать подсказку типа с помощью Callable[[Arg1Type, Arg2Type], ReturnType].

Например:

from typing import Callable

def feeder(get_next_item: Callable[[], str]) -> None:
    # Тело

def async_query(on_success: Callable[[int], None],
                on_error: Callable[[int, Exception], None]) -> None:
    # Тело

Можно объявить возвращаемый тип вызываемого объекта без указания сигнатуры вызова, подставив буквальное многоточие вместо списка аргументов в подсказке типа: Callable[..., ReturnType].

Универсальные

Поскольку информация о типах объектов, хранящихся в контейнерах, не может быть статически выведена универсальным способом, абстрактные базовые классы были расширены для поддержки индексирования для обозначения ожидаемых типов для элементов контейнера.

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')      # Объявить переменную типа

def first(l: Sequence[T]) -> T:   # Универсальная функция
    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 принимает один параметр типа T. Это также делает T допустимым как тип в теле класса.

Базовый класс 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)

У универсального типа может быть любое количество переменных типа, и переменные типа могут быть ограничены:

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]):   # НЕВЕРНО
    ...

Вы можете использовать множественное наследование с 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): # Такой же как Iterable[Any]

Также поддерживаются пользовательские псевдонимы универсального типа. Примеры:

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

# Тип возврата здесь такой же, как 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: # Такой же как Iterable[Tuple[T, T]]
    return sum(x*y for x, y in v)

Изменено в версии 3.7: У Generic больше нет настраиваемого метакласса.

Определенный пользователем универсальный класс может иметь ABC в качестве базовых классов без конфликта метаклассов. Универсальные метаклассы не поддерживаются. Результат параметризации универсальных шаблонов кэшируется, и большинство типов в модуле типизации являются хешируемыми и сопоставимыми по равенству.

Тип Any

Особый тип — Any. Средство проверки статического типа будет рассматривать каждый тип как совместимый с Any и Any как совместимый с каждым типом.

Это означает, что можно выполнить любую операцию или вызов метода для значения типа Any и присвоить его любой переменной:

from typing import Any

a = None    # тип: Any
a = []      # OK
a = 2       # OK

s = ''      # тип: str
s = a       # OK

def foo(item: Any) -> int:
    # Проверки типов; элемент может быть любым типом,
    # и у этого типа может быть метод bar
    item.bar()
    ...

Обратите внимание, что при присвоении значения типа Any более точному типу проверка типов не выполняется. Например, средство проверки статического типа не сообщило об ошибке при присвоении a s, хотя s был объявлен как имеющий тип str и получил значение int во время выполнения!

Кроме того, все функции без возвращаемого типа или типов параметров неявно по умолчанию будут использовать Any:

def legacy_parser(text):
    ...
    return data

# Средство проверки статического типа будет рассматривать вышеуказанное как
# имеющее ту же сигнатуру, что и:
def legacy_parser(text: Any) -> Any:
    ...
    return data

Такое поведение позволяет использовать Any как аварийный люк, когда вам нужно смешивать динамически и статически типизированный код.

Сравните поведение Any с поведением object. Подобно Any, каждый тип является подтипом object. Однако, в отличие от Any, обратное неверно: object — это не подтип любого другого типа.

Это означает, что если тип значения — object, средство проверки типов отклонит почти все операции с ним, и присвоение его переменной (или использование в качестве возвращаемого значения) более специализированного типа является ошибкой типа. Например:

def hash_a(item: object) -> int:
    # Терпит неудачу; объект не имеет метода "magic".
    item.magic()
    ...

def hash_b(item: Any) -> int:
    # Проверки типа
    item.magic()
    ...

# Проверки типа, так как ints и strs являются подклассы объекта
hash_a(42)
hash_a("foo")

# Проверки типа, так как Any совместим со всеми типами
hash_b(42)
hash_b("foo")

Использовать object, чтобы указать, что значение может быть любого типа безопасным способом. Использовать Any, чтобы указать, что значение динамически типизировано.

Номинальные и структурные подтипы

Первоначально PEP 484 определил систему статических типов Python как использующую номинальный подтип. Это означает, что разрешён класс A там, где ожидается класс B тогда и только тогда, когда A является подклассом B.

Это требование ранее также применялось к абстрактным базовым классам, таким как Iterable. Проблема с этим подходом заключается в том, что класс должен быть явно помечен для их поддержки, что является непитоническим и непохожим на то, что обычно делают в идиоматическом динамически типизированном коде Python. Например, это соответствует PEP 484:

from typing import Sized, Iterable, Iterator

class Bucket(Sized, Iterable[int]):
    ...
    def __len__(self) -> int: ...
    def __iter__(self) -> Iterator[int]: ...

PEP 544 позволяет решить эту проблему, позволяя пользователям писать приведенный выше код без явных базовых классов в определении класса, что позволяет неявно рассматривать Bucket как подтип как Sized, так и Iterable[int] средствами проверки статических типов. Это известно как структурный подтип (или статическая утиная типизация):

from typing import Iterator, Iterable

class Bucket:  # Примечание: базовые классы отсутствуют
    ...
    def __len__(self) -> int: ...
    def __iter__(self) -> Iterator[int]: ...

def collect(items: Iterable[int]) -> int: ...
result = collect(Bucket())  # Проходит проверку типа

Более того, создав подкласс специального класса Protocol, пользователь может определять новые настраиваемые протоколы, чтобы в полной мере насладиться структурным подтипом (см. примеры ниже).

Классы, функции и декораторы

Модуль определяет следующие классы, функции и декораторы:

class typing.TypeVar

Тип переменная.

Использование:

T = TypeVar('T')  # Может быть что угодно
A = TypeVar('A', str, bytes)  # Должно быть str или bytes

Переменные типа существуют в первую очередь для целей проверки статических типов. Они служат параметрами для универсальных типов, а также для определений универсальных функций. См. класс Generic для получения дополнительной информации об универсальных типах. Generic функции работают следующим образом:

def repeat(x: T, n: int) -> Sequence[T]:
    """Возвращает список, содержащий n ссылок на x."""
    return [x]*n

def longest(x: A, y: A) -> A:
    """Возвращает самую длинную из двух строк."""
    return x if len(x) >= len(y) else y

Сигнатура последнего примера по сути является перегрузкой (str, str) -> str и (bytes, bytes) -> bytes. Также обратите внимание, что если аргументы являются экземплярами некоторого подкласса str, возвращаемый тип по-прежнему будет обычным str.

Во время выполнения isinstance(x, T) поднимет TypeError. Как правило, isinstance() и issubclass() не следует использовать с типами.

Переменные типа могут быть помечены как ковариантные или контравариантные путём передачи covariant=True или contravariant=True. См. PEP 484 для получения более подробной информации. По умолчанию переменные типа неизменны. В качестве альтернативы переменная типа может указывать верхнюю границу с помощью bound=<type>. Это означает, что фактический тип, замененный (явно или неявно) для переменной типа, должен быть подклассом граничного типа, см. PEP 484.

class typing.Generic

Абстрактный базовый класс для универсальных типов.

Универсальный тип обычно объявляется путём наследования от экземпляра этого класса с одной или несколькими переменными типа. Например, общий тип сопоставления может быть определен как:

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

Затем этот класс можно использовать следующим образом:

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.Protocol(Generic)

Базовый класс для классов протокола. Классы протокола определяются следующим образом:

class Proto(Protocol):
    def meth(self) -> int:
        ...

Такие классы в основном используются со средствами проверки статического типа, которые распознают структурные подтипы (например, статическая утиная типизация):

class C:
    def meth(self) -> int:
        return 0

def func(x: Proto) -> int:
    return x.meth()

func(C())  # Проходит статическая проверка типа

Подробности см. в PEP 544. Классы протоколов, декорированные runtime_checkable() (описанные ниже), действуют как простые протоколы времени выполнения, которые проверяют только наличие заданных атрибутов, игнорируя их сигнатуры типов.

Например, классы протоколов могут быть общими:

class GenProto(Protocol[T]):
    def meth(self) -> T:
        ...

Добавлено в версии 3.8.

class typing.Type(Generic[CT_co])

Переменная, помеченная как C, может принимать значение типа C. Напротив, переменная, аннотированная Type[C], может принимать значения, которые сами являются классами — в частности, она будет принимать объект класса из C. Например:

a = 3         # Имеет тип 'int'
b = int       # Имеет тип 'Type[int]'
c = type(a)   # Также имеет тип 'Type[int]'

Обратите внимание, что Type[C] ковариантен:

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

# Принимает 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[BasicUser, 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

ABC с одним абстрактным методом __int__.

class typing.SupportsFloat

ABC с одним абстрактным методом __float__.

class typing.SupportsComplex

ABC с одним абстрактным методом __complex__.

class typing.SupportsBytes

ABC с одним абстрактным методом __bytes__.

class typing.SupportsIndex

ABC с одним абстрактным методом __index__.

Добавлено в версии 3.8.

class typing.SupportsAbs

ABC с одним абстрактным методом __abs__, ковариантным по типу возвращаемого значения.

class typing.SupportsRound

ABC с одним абстрактным методом __round__, ковариантным по типу возвращаемого значения.

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. Этот тип можно использовать следующим образом:

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.

Этот тип представляет типы байтовых последовательностей bytes, bytearray и memoryview.

В качестве сокращения для этого типа можно использовать bytes для аннотирования аргументов любого из типов, упомянутых выше.

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

Универсальная версия collections.deque.

Добавлено в версии 3.5.4.

Добавлено в версии 3.6.1.

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

Универсальная версия list. Полезно для аннотирования возвращаемых типов. Для аннотирования аргументов предпочтительно использовать абстрактный тип коллекции, такой как Sequence или Iterable.

Этот тип можно использовать следующим образом:

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. Полезно для аннотирования возвращаемых типов. Для аннотирования аргументов предпочтительно использовать абстрактный тип коллекции, такой как 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:

from typing import List, Coroutine
c = None # тип: 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. Полезно для аннотирования возвращаемых типов. Для аннотирования аргументов предпочтительно использовать абстрактный тип коллекции, такой как Mapping.

Этот тип можно использовать следующим образом:

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'

Обратите внимание, что в отличие от многих других универсальных шаблонов в модуле типизации, SendType из Generator ведет себя контравариантно, а не ковариантно или инвариантно.

Если ваш генератор выдает только значения, установить SendType и ReturnType на 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.6.1.

class typing.Text

Text — это псевдоним для str. Он предоставляется для обеспечения прямого совместимого пути для кода Python 2: в Python 2 Text является псевдонимом для unicode.

Использовать Text, чтобы указать, что значение должно содержать строку Юникод способом, совместимым как с Python 2, так и с Python 3:

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]) представляют типы потоков ввода-вывода, такие как возвращаемые open().

class typing.Pattern
class typing.Match

Эти псевдонимы типов соответствуют типам возврата из re.compile() и re.match(). Эти типы (и соответствующие функции) являются общими в AnyStr и могут быть определены как Pattern[str], Pattern[bytes], Match[str] или Match[bytes].

class typing.NamedTuple

Набранная версия collections.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

Поля со значением по умолчанию должны стоять после любых полей без значения по умолчанию.

У результирующего класса есть дополнительный атрибут __annotations__, дающий dict, который сопоставляет имена полей с типами полей. (Имена полей находятся в атрибуте _fields, а значения по умолчанию — в атрибуте _field_defaults, оба из которых являются частью API именованного картежа.)

У подклассов NamedTuple также могут быть строки документации и методы:

class Employee(NamedTuple):
    """Представляет сотрудника."""
    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: Добавлена поддержка значений по умолчанию, методов и строк документации.

Устарело с версии 3.8, будет удалено в 3.9 версии.: Устарел атрибут _field_types в пользу более стандартного атрибута __annotations__, который имеет ту же информацию.

Изменено в версии 3.8: Атрибуты _field_types и __annotations__ теперь являются обычными словарями, а не экземплярами OrderedDict.

class typing.TypedDict(dict)

Простое типизированное пространство имён. Во время выполнения он эквивалентен простому dict.

TypedDict создаёт тип словаря, который ожидает, что все его экземпляры будут иметь определенный множество ключей, где каждый ключ связан со значением согласованного типа. Это ожидание не проверяется во время выполнения, а выполняется только средствами проверки типов. Использование:

class Point2D(TypedDict):
    x: int
    y: int
    label: str

a: Point2D = {'x': 1, 'y': 2, 'label': 'good'}  # Хорошо
b: Point2D = {'z': 3, 'label': 'bad'}           # Не удалось проверить тип

assert Point2D(x=1, y=2, label='first') == dict(x=1, y=2, label='first')

Информацию о типе для интроспекции можно получить через Point2D.__annotations__ и Point2D.__total__. Чтобы разрешить использование этой функции со старыми версиями Python, которые не поддерживают PEP 526, TypedDict поддерживает две дополнительные эквивалентные синтаксические формы:

Point2D = TypedDict('Point2D', x=int, y=int, label=str)
Point2D = TypedDict('Point2D', {'x': int, 'y': int, 'label': str})

По умолчанию все ключи должны присутствовать в TypedDict. Это можно изменить, указав совокупность. Использование:

class point2D(TypedDict, total=False):
    x: int
    y: int

Это означает, что в point2D TypedDict может быть пропущен любой из ключей. Ожидается, что средство проверки типов будет поддерживать только буквальное значение ложь или истина в качестве значения общего аргумента. По умолчанию установлено значение истина, и все элементы, определенные в теле класса, являются обязательными.

См. PEP 589 для получения дополнительных примеров и подробных правил использования TypedDict.

Добавлено в версии 3.8.

class typing.ForwardRef

Класс, используемый для внутреннего типизационного представления строковых прямых ссылок. Например, List["SomeClass"] неявно преобразуется в List[ForwardRef("SomeClass")]. Этот класс не должен создаваться пользователем, но может использоваться инструментами самоанализа.

Добавлено в версии 3.7.4.

typing.NewType(name, tp)

Вспомогательная функция для указания отдельного типа для проверки типов, см. 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__. Кроме того, прямые ссылки, закодированные как строковые литералы, обрабатываются путём их вычисления в пространствах имён globals и locals. При необходимости для аннотаций функций и методов добавляется Optional[t], если установлено значение по умолчанию, равное None. Для класса C возвращает словарь, построенный путём слияния всех __annotations__ вдоль C.__mro__ в обратном порядке.

typing.get_origin(tp)
typing.get_args(tp)

Обеспечить базовый самоанализ для универсальных типов и специальных форм ввода.

Для типизирующего объекта формы X[Y, Z, ...] эти функции возвращают X и (Y, Z, ...). Если X является общим псевдонимом для встроенного класса или класса collections, он нормализуется до исходного класса. Для неподдерживаемых объектов возвращает None и () соответственно. Примеры:

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

Декоратор, указывающий контролерам типов, что декорированный метод не может быть переопределен, а декорированный класс не может быть разделен на подклассы. Например:

class Base:
    @final
    def done(self) -> None:
        ...
class Sub(Base):
    def done(self) -> None:  # Ошибка, указанная средством проверки типа
          ...

@final
class Leaf:
    ...
class Other(Leaf):  # Ошибка, указанная средством проверки типа
    ...

Эти свойства не проверяются во время выполнения. См. PEP 591 для получения более подробной информации.

Добавлено в версии 3.8.

@typing.no_type_check

Декоратор, указывающий, что аннотации не являются подсказками типа.

Работает как класс или функция декоратор. С классом он рекурсивно применяется ко всем методам, определенным в этом классе (но не к методам, определенным в его суперклассах или подклассах).

Изменяет функции на месте.

@typing.no_type_check_decorator

Декоратор, чтобы дать другому декоратору эффект no_type_check().

Это оборачивает декоратор чем-то, что обертывает декорированную функцию в no_type_check().

@typing.type_check_only

Декоратор, отмечающий недоступность класса или функции во время выполнения.

Этот декоратор сам по себе недоступен во время выполнения. В основном он предназначен для маркировки классов, определенных в файлах-заглушках типов, если реализация возвращает экземпляр частного класса:

@type_check_only
class Response:  # частный или недоступный во время выполнения
    code: int
    def get_header(self, name: str) -> str: ...

def fetch_response() -> Response: ...

Обратите внимание, что возвращать экземпляры частных классов не рекомендуется. Обычно предпочтительнее сделать такие классы общедоступными.

@typing.runtime_checkable

Отметить класс протокола как протокол времени выполнения.

Такой протокол можно использовать с isinstance() и issubclass(). Это вызывает TypeError при применении к непротокольному классу. Это позволяет провести простую структурную проверку, очень похожую на «пони с одной уловкой» в collections.abc, например, Iterable. Например:

@runtime_checkable
class Closable(Protocol):
    def close(self): ...

assert isinstance(open('/some/file'), Closable)

Предупреждение: проверяет только наличие требуемых методов, но не их типовые сигнатуры !

Добавлено в версии 3.8.

typing.Any

Специальный тип, указывающий на неограниченный тип.

  • Каждый тип совместим с Any.
  • Any совместим со всеми типами.
typing.NoReturn

Специальный тип, указывающий, что функция никогда не возвращается. Например:

from typing import NoReturn

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

Добавлено в версии 3.5.4.

Добавлено в версии 3.6.2.

typing.Union

Тип союза; Union[X, Y] означает либо X, либо Y.

Чтобы определить объединение, использовать, например, Union[int, str]. Подробности:

  • Аргументы должны быть типами и должен быть хотя бы один.

  • Союзы союзов сглаживаются, например .:

    Union[Union[int, str], float] == Union[int, str, float]
    
  • Союзы одного аргумента исчезают, например:

    Union[int] == int  # Конструктор фактически возвращает int
    
  • Избыточные аргументы пропускаются, например .:

    Union[int, str, int] == Union[int, str]
    
  • При сравнении объединений порядок аргументов игнорируется, например:

    Union[int, str] == Union[str, int]
    
  • Вы не можете создать подкласс или создать союз.

  • Нельзя писать Union[X][Y].

  • Вы можете использовать Optional[X] как сокращение для Union[X, None].

Изменено в версии 3.7: Не удаляет явные подклассы из объединений во время выполнения.

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[()].

Пример: Tuple[T1, T2] — это кортеж из двух элементов, соответствующих переменным типа T1 и T2. Tuple[int, float, str] — это кортеж, состоящий из типа int, float и строки.

Чтобы указать кортеж переменной длины однородного типа, использовать буквальное многоточие, например Tuple[int, ...]. Обычный Tuple эквивалентен Tuple[Any, ...] и, в свою очередь, tuple.

typing.Callable

Вызываемый тип; Callable[[int], str] — это функция от (int) -> str.

Синтаксис индексирования всегда должен использоваться ровно с двумя значениями: списком аргументов и типом возвращаемого значения. Список аргументов должен быть списком типов или многоточием; возвращаемый тип должен быть одного типа.

Не существует синтаксиса для указания необязательных аргументов или ключевых аргументов; такие типы функций редко используются как типы обратного вызова. Callable[..., ReturnType] (буквальное многоточие) можно использовать для ввода подсказки вызываемого объекта, принимающего любое количество аргументов и возвращающего ReturnType. Обычный Callable эквивалентен Callable[..., Any] и, в свою очередь, collections.abc.Callable.

typing.Literal

Тип, который можно использовать для указания средствам проверки типов, что соответствующая переменная или параметр функции имеет значение, эквивалентное предоставленному литералу (или одному из нескольких литералов). Например:

def validate_simple(data: Any) -> Literal[True]:  # всегда возвращает True
    ...

MODE = Literal['r', 'rb', 'w', 'wb']
def open_helper(file: str, mode: MODE) -> str:
    ...

open_helper('/some/path', 'r')  # Проходит проверку типа
open_helper('/other/path', 'typo')  # Ошибка при проверке типа

Literal[...] не может быть разделен на подклассы. Во время выполнения в качестве аргумента типа для Literal[...] допускается произвольное значение, но средства проверки типов могут налагать ограничения. См. PEP 586 для получения дополнительных сведений о типах литералов.

Добавлено в версии 3.8.

typing.ClassVar

Конструкция специального типа для обозначения переменных класса.

Как представлено в PEP 526, обёрнутая в ClassVar аннотация переменной указывает, что данный атрибут предназначен для использования в качестве переменной класса и не должен устанавливаться в экземплярах этого класса. Использование:

class Starship:
    stats: ClassVar[Dict[str, int]] = {} # переменная класса
    damage: int = 10                     # сущность переменной

ClassVar принимает только типы и не может быть дополнительно проиндексирован.

ClassVar сам по себе не является классом и не должен использоваться с isinstance() или issubclass(). ClassVar не изменяет поведение среды выполнения Python, но может использоваться сторонними программами проверки типов. Например, средство проверки типов может пометить следующий код как ошибку:

enterprise_d = Starship(3000)
enterprise_d.stats = {} # Ошибка при установке переменной класса для сущности
Starship.stats = {}     # Все в порядке

Добавлено в версии 3.5.3.

typing.Final

Специальная конструкция типизации, указывающая контролерам типов, что имя не может быть повторно присвоено или переопределено в подклассе. Например:

MAX_SIZE: Final = 9000
MAX_SIZE += 1  # Ошибка, указанная средством проверки типа

class Connection:
    TIMEOUT: Final[int] = 10

class FastConnector(Connection):
    TIMEOUT = 1  # Ошибка, указанная средством проверки типа

Эти свойства не проверяются во время выполнения. См. PEP 591 для получения более подробной информации.

Добавлено в версии 3.8.

typing.AnyStr

AnyStr — это переменная типа, определенная как AnyStr = TypeVar('AnyStr', str, bytes).

Он предназначен для использования в функциях, которые могут принимать строки любого типа, не позволяя смешивать разные типы строк. Например:

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

concat(u"foo", u"bar")  # ОК, вывод имеет тип 'unicode'
concat(b"foo", b"bar")  # ОК, вывод имеет тип 'bytes'
concat(u"foo", b"bar")  # Ошибка, не удается смешать Юникод и байты
typing.TYPE_CHECKING

Специальная константа, которая считается 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.