Python LanguageТип подсказки

Синтаксис

  • typing.Callable [[int, str], None] -> def func (a: int, b: str) -> None
  • typing.Mapping [str, int] -> {"a": 1, "b": 2, "c": 3}
  • typing.List [int] -> [1, 2, 3]
  • typing.Set [int] -> {1, 2, 3}
  • typing.Optional [int] -> None или int
  • typing.Sequence [int] -> [1, 2, 3] или (1, 2, 3)
  • typing.Any -> Любой тип
  • typing.Union [int, str] -> 1 или "1"
  • T = typing.TypeVar ('T') -> Общий тип

замечания

Тип Hinting, как указано в PEP 484 , является формализованным решением для статического указания типа значения для кода Python. Появляясь рядом с модулем typing , подсказки типа предлагают пользователям Python возможность комментировать их код, тем самым помогая контролерам типов, а косвенно, документируя их код с дополнительной информацией.

Общие типы

Тип typing.TypeVar - это фабрика общего типа. Основная задача состоит в том, чтобы служить параметром / заполнителем для общих аннотаций функции / класса / метода:

import typing

T = typing.TypeVar("T")

def get_first_element(l: typing.Sequence[T]) -> T:
    """Gets the first element of a sequence."""
    return l[0]

Добавление типов к функции

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

def two_sum(a, b):
    return a + b

two_sum этот код, нельзя смело и без сомнения указать тип аргументов функции two_sum . Он работает как при int значений int :

print(two_sum(2, 1))  # result: 3

и со строками:

print(two_sum("a", "b"))  # result: "ab"

и с другими значениями, такими как list s, tuple s et cetera.

Из-за этой динамической природы типов python, где многие применимы для данной операции, любая проверка типов не сможет обоснованно утверждать, должен ли разрешаться вызов этой функции или нет.

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

Чтобы указать, что мы хотим только разрешить типы int мы можем изменить определение функции следующим образом:

def two_sum(a: int, b: int):
    return a + b

Аннотации следуют за именем аргумента и разделяются символом :

Точно так же, чтобы указать только str типа разрешены, мы бы изменить нашу функцию , чтобы определить его:

def two_sum(a: str, b: str): 
    return a + b

Помимо указания типа аргументов, можно также указать возвращаемое значение вызова функции. Это делается добавлением символа -> за которым следует тип после закрывающей круглой скобки в списке аргументов, но до : в конце объявления функции:

def two_sum(a: int, b: int) -> int: 
    return a + b

Теперь мы указали, что возвращаемое значение при вызове two_sum должно иметь тип int . Аналогичным образом мы можем определить соответствующие значения для str , float , list , set и других.

Хотя подсказки типов в основном используются контролерами типов и IDE, иногда вам может потребоваться их получить. Это можно сделать с __annotations__ специального атрибута __annotations__ :

two_sum.__annotations__
# {'a': <class 'int'>, 'b': <class 'int'>, 'return': <class 'int'>}

Участники и методы класса

class A:
    x = None  # type: float
    def __init__(self, x: float) -> None:
        """
        self should not be annotated
        init should be annotated to return None
        """
        self.x = x
    
    @classmethod
    def from_int(cls, x: int) -> 'A': 
        """
        cls should not be annotated
        Use forward reference to refer to current class with string literal 'A'
        """
        return cls(float(x))

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

Переменные и атрибуты

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

x = 3  # type: int
x = negate(x)
x = 'a type-checker might catch this error'
Python 3.x 3.6

Начиная с Python 3.6, есть также новый синтаксис для переменных аннотаций . Вышеприведенный код может использовать форму

x: int = 3

В отличие от комментариев, также можно просто добавить подсказку типа к переменной, которая ранее не была объявлена, без установки для нее значения:

y: int

Кроме того, если они используются в модуле или уровне класса, подсказки типа могут быть получены с помощью typing.get_type_hints(class_or_module) :

class Foo:
    x: int
    y: str = 'abc'

print(typing.get_type_hints(Foo))
# ChainMap({'x': <class 'int'>, 'y': <class 'str'>}, {})

Кроме того, к ним можно получить доступ с помощью специальной переменной или атрибута __annotations__ :

x: int
print(__annotations__)
# {'x': <class 'int'>}

class C:
    s: str
print(C.__annotations__)
# {'s': <class 'str'>}

NamedTuple

Создание именованного набора с подсказками типа выполняется с помощью функции NamedTuple из модуля typing :

import typing
Point = typing.NamedTuple('Point', [('x', int), ('y', int)])

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

Введите подсказки для аргументов ключевых слов

def hello_world(greeting: str = 'Hello'):
    print(greeting + ' world!')

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