Аннотации типов в Python

Введение

Примеры

  • Общие типы

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

    `` `импорт печатать

    T = typing.TypeVar ("T")

    def get_first_element (l: typing.Sequence [T]) -> T: "" "Получает первый элемент последовательности." "" return l [0]

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

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

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

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

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

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

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

    а также с другими значениями, например, list с, tuple ов и так далее.

    Из-за этой динамической природы типов 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 и другие.

    Хотя подсказки типов в основном используются средствами проверки типов и средами разработки, иногда вам может потребоваться получить их. Это может быть сделано с помощью __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.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 с намеками типа осуществляется с помощью функции NamedTuple из typing модуля:

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

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

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

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

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

Синтаксис

Параметры

Примечания