Как явно указать тип в python
Перейти к содержимому

Как явно указать тип в python

  • автор:

Аннотации переменных в Python

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

Обложка поста Аннотации переменных в Python

В Python 3.6 появилась такая интересная особенность, как синтаксис для аннотаций переменных. Подробнее про это нововведение можно прочитать в PEP 526. Суть этого PEP заключается в том, чтобы перевести идею аннотаций типов (PEP 484) на её следующую логическую ступень, т.е. сделать возможным указание типов переменных, включая поля классов и объектов.

Следует принять во внимание, что это нововведение не делает Python статически типизированным языком. Интерпретатору всё равно, какой тип указан у переменной. Тем не менее в среде разработки на Python или другом инструменте вроде pylint может быть включена функция проверки аннотаций, которая сообщит вам, если вы сначала указали один тип переменной, а затем попытались использовать её в качестве другого типа далее в программе.

Давайте взглянем на простой пример, чтобы посмотреть, как это работает:

# annotate.py name: str = 'Mike' 

В нашем файле annotate.py мы создали переменную name и добавили аннотацию, говорящую о том, что это строка. Аннотацию можно добавить, поставив двоеточие после имени переменной и затем указав нужный тип. Присваивать значение переменной вовсе не обязательно:

# annotate.py name: str 

Прим.перев. Указать тип в Python 3.5 подобным образом не выйдет. Вместо этого есть возможность указывать тип в комментарии:

# annotate.py name = 'Mike' # type: str 

Все переменные с аннотациями добавляются в атрибут __annotations__ модуля или класса. Давайте импортируем первую версию нашего модуля annotate и получим доступ к этому атрибуту:

>>> import annotate >>> annotate.__annotations__ > >>> annotate.name 'Mike' 

Как вы видите, атрибут __annotations__ возвращает словарь с аннотацией в качестве значения. Давайте добавим ещё несколько аннотаций в наш модуль и посмотрим, как изменится атрибут __annotations__ :

# annotate.py name: str = 'Mike' ages: list = [12, 20, 32] class Car: variable: dict 

В этом примере мы добавили список с аннотацией и класс, содержащий переменную с аннотацией. Теперь давайте импортируем новую версию нашего модуля и посмотрим на атрибут __annotations__ :

>>> import annotate >>> annotate.__annotations__ , 'ages': > >>> annotate.Car.__annotations__ > >>> car = annotate.Car() >>> car.__annotations__ > 

В этот раз в словаре находится два объекта. Как вы могли заметить, в нём нет поля класса. Чтобы получить к нему доступ, мы должны обратиться к классу Car напрямую или создать экземпляр класса и получить атрибут таким образом.

Заключение

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

Как задать тип возвращаемого значения функции в Python?

Для того, чтобы задать тип возвращаемого значения функции, используем аннотацию типов. Тип возвращаемого значения указывается после аргументов функции. Добавляем символы «->»,пробел и указываем тип. После чего ставим завершающее двоеточие:

def my_function(number1: int, number2: int) -> int: result = number1 + number2 . 

Python. Урок 18. Аннотация типов в Python

Follow us on Google Plus Follow us on rss

Этот урок посвящен аннотациям типов в Python. Рассмотрен вопрос контроля типов переменных и функций с использованием комментариев и аннотаций. Приведено описание PEP‘ов, регламентирующих работу с аннотациями, и представлены примеры работы с инструментом mypy для анализа Python кода.

  • Зачем нужны аннотации?
  • Контроль типов в Python
  • Обзор PEP’ов регламентирующий работу с аннотациями
  • Использование аннотаций в функциях
    • Указание типа аргументов и возвращаемого значения
    • Доступ к аннотациям функции
    • Создание аннотированных переменных
    • Контроль типов с использованием аннотаций

    Зачем нужны аннотации?

    Для начала ответим на вопрос: зачем нужны аннотации в Python ? Если кратко, то ответ будет таким: для того чтобы повысить информативность исходного кода, и иметь возможность с помощью сторонних инструментов производить его анализ. Одной из наиболее востребованных, в этом смысле, тем является контроль типов переменных. Несмотря на то, что Python – это язык с динамической типизацией, иногда возникает необходимость в контроле типов.

    Согласно PEP 3107 могут быть следующие варианты использования аннотаций:

    • проверка типов;
    • расширение функционала IDE в части предоставления информации об ожидаемых типах аргументов и типе возвращаемого значения у функций;
    • перегрузка функций и работа с дженериками;
    • взаимодействие с другими языками;
    • использование в предикатных логических функциях;
    • маппинг запросов в базах данных;
    • маршалинг параметров в RPC (удаленный вызов процедур).

    Контроль типов в Python

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

    Выглядит это так:

    name = "John" # type: str

    Мы создали переменную с именем name и предполагаем, что ее тип – str . Естественно, для самого интерпретатора Python это не имеет значения, мы, без труда можем продолжить нашу мини программу таким образом.

    name = "John" # type: str print(name) name = 10 print(name)

    И это будет корректно с точки зрения Python . Но если необходимо проконтролировать, что переменной name будут присваиваться значения только строкового типа, мы должны: во-первых указать в комментарии о нашем намерение – это мы сделали, во-вторых использовать специальный инструмент, который выполнит соответствующую проверку. Таким инструментом является mypy .

    Установить его можно с помощью pip :

    python -m pip install mypy

    Если мы сохраним приведенный выше код в файле type_tester.py и выполним следующую команду:

    python -m mypy test_type.py

    Получим такое сообщение:

    test_type.py:3: error: Incompatible types in assignment (expression has type “int”, variable has type “str”)

    Оно говорит о том, что обнаружено несоответствие типов в операции присваивание: переменная имеет тип “ str “, а ей присвоено значение типа “ int “.

    Обзор PEP’ов регламентирующий работу с аннотациями

    Начнем наше введение в тему аннотаций в Python с краткого обзора четырех ключевых документов:

    Первый из них PEP 3107 — Function Annotations , является исторически первым из перечисленных выше документов. В нем описывается синтаксис использования аннотаций в функциях Python . Важным является то, что аннотации не имеют никакого семантического значения для интерпретатора Python и предназначены только для анализа сторонними приложениями. Аннотировать можно аргументы функции и возвращаемое ей значение.

    Следующий документ – PEP 484 — Type Hints . В нем представлены рекомендации по использованию аннотаций типов. Аннотация типов упрощает статический анализ кода, рефакторинг, контроль типов в рантайме и кодогенерацию, использующую информацию о типах. В рамках данного документа, определены следующие варианты работы с аннотациями: использование аннотаций в функциях согласно PEP 3107, аннотация типов переменных через комментарии в формате # type: type_name и использование stub -файлов (см. разделы Использование аннотаций в функциях и Аннотация переменных).

    В PEP 526 — Syntax for Variable Annotations приводится описание синтаксиса для аннотации типов переменных (базируется на PEP 484), использующего языковые конструкции, встроенные в Python (см. раздел Аннотация переменных).

    PEP 563 — Postponed Evaluation of Annotations . Данный PEP вступил в силу с выходом Python 3.7. У подхода работы с аннотация до этого PEP’а был ряд проблем связанных с тем, что определение типов переменных (в функциях, классах и т.п.) происходит во время импорта модуля, и может сложится такая ситуация, что тип переменной объявлен, но информации об этом типе ещё нет, в таком случае тип указывают в виде строки – в кавычках. В PEP 563 предлагается использовать отложенную обработку аннотаций, это позволяет определять переменные до получения информации об их типах и ускоряет выполнение программы, т.к. при загрузке модулей не будет тратится время на проверку типов – это будет сделано перед работой с переменными.

    Теперь более подробно остановимся на использовании аннотаций, опираясь на перечисленные выше PEP ’ы.

    Использование аннотаций в функциях

    Указание типов аргументов и возвращаемого значения

    В функциях мы можем аннотировать аргументы и возвращаемое значение. Выглядеть это может так.

    def repeater(s: str, n: int) -> str: return s * n

    Аннотация для аргумента определяется через двоеточие после его имени.

    имя_аргумента: аннотация

    Аннотация, определяющая тип возвращаемого функцией значения, указывается после ее имени с использованием символов ->

    def имя_функции() -> тип

    Для лямбд аннотации не поддерживаются.

    Доступ к аннотациям функции

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

    Содержимое repeater. __annotations__

    Аннотация переменных

    Создание аннотированных переменных

    Можно использовать один из трех способов создания аннотированных переменных.

    var = value # type: annotation var: annotation; var = value var: annotation = value

    Рассмотрим это на примере работы со строковой переменной с именем name.

    name = “John” # type: str name:str; name = “John” name: str = “John”

    Приведем еще несколько примеров.

    # список scores: List[int] = [] scores.append(1) # кортеж pack: Tuple[int, …] = (1, 2, 3) # логическая переменная flag: bool flag = True # класс class Point: x: int y: int def __init__(self, x: int, y: int): self.x = x self.y = y

    Контроль типов с использованием аннотаций

    Для проверки можно использовать уже знакомый нам инструмент mypy . Напишем вот такой код.

    a:int = 10 b:int = 15 def sq_sum(v1:int, v2:int) -> int: return v1**2 + v2**2 print(sq_sum(a, b))

    Сохраним его в файле с именем work.py и запустим mypy для анализа.

    python -m mypy work.py

    Если не указывать дополнительные ключи, то окно консоли будет чистым, т.к. mypy не найдет никаких ошибок в вашем коде.

    Но если заменить первую строку

    a: int = 10
    a = 10.3

    и вновь запустить mypy , то увидим вот такое сообщение:

    work.py:7: error: Argument 1 to “sq_sum” has incompatible type “float”; expected “int”

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

    Отложенная проверка аннотаций

    До выхода Python 3.7 определение типов в аннотациях происходило во время импорта модуля, что приводило к проблеме. Например, если выполнить следующий код:

    class Rectangle: def __init__(self, height: int, width: int, color: Color) -> None: self.height = height self.width = width self.color = color

    То возникнет ошибка NameError: name ‘Color’ is not defined. Она связана с тем, что переменная color имеет тип Color, который пока ещё не объявлен.

    В таком случае, мы можем указать тип Color в кавычках, но это не очень удобно.

    class Rectangle: def __init__(self, height: int, width: int, color: "Color") -> None: self.height = height self.width = width self.color = color

    Эту проблему можно решить воспользовавшись отложенной обработкой аннотаций из Python 3.7.

    from __future__ import annotations class Rectangle: def __init__(self, height: int, width: int, color: Color) -> None: self.height = height self.width = width self.color = color class Color: def __init__(self, r: int, g: int, b: int) -> None: self.R = r self.G = g self.B = b rect = Rectangle(1, 2, Color(255, 255, 255))

    Можете проверить, что без строки from __future__ import annotations эта программа выполняться не будет.

    P.S.

    Если вам интересна тема анализа данных, то мы рекомендуем ознакомиться с библиотекой Pandas. На нашем сайте вы можете найти вводные уроки по этой теме. Все уроки по библиотеке Pandas собраны в книге “Pandas. Работа с данными”.

    Раздел: Python Уроки по Python Метки: Python, аннотации в Python, Уроки Python

    Python. Урок 18. Аннотация типов в Python : 2 комментария

    1. Алексей 08.11.2020 Благодарю, хорошее объяснение.

    Указание типа переменной в python?

    Объясните, имеет ли вообще смысл указывать тип аргументов? Единственный плюс (даже не питона, а среды), который я нашел, это то, что PyCharm при указании типа аргумента будет знать тип переменной и будет предлагать методы этого класса при написании variable.

    Отслеживать
    6,343 5 5 золотых знаков 25 25 серебряных знаков 54 54 бронзовых знака
    задан 24 янв 2018 в 15:41
    113 1 1 золотой знак 1 1 серебряный знак 5 5 бронзовых знаков
    24 янв 2018 в 15:52
    Подробнее можно прочитать здесь: PEP 3107 — Function Annotations
    12 фев 2019 в 12:48

    3 ответа 3

    Сортировка: Сброс на вариант по умолчанию

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

    Отслеживать
    ответ дан 24 янв 2018 в 17:32
    Vadim Toptunov Vadim Toptunov
    345 2 2 серебряных знака 7 7 бронзовых знаков

    На сегодняшний день аннотации переменных полезны только для IDE и линтеров. Впрочем, на мой взгляд, и эта полезность сомнительна.

    Отслеживать
    ответ дан 24 янв 2018 в 15:48
    Sergey Gornostaev Sergey Gornostaev
    66.4k 6 6 золотых знаков 51 51 серебряный знак 112 112 бронзовых знаков
    Эээээ, полезность линтеров сомнительна??
    24 янв 2018 в 17:18
    @andreymal полезность аннотаций сомнительна.
    24 янв 2018 в 17:20

    Аннотации упрощают линтерам анализ и обнаружение ошибок, значит сомнительность полезности аннотаций сомнительна, я чего-то не понимаю?)

    24 янв 2018 в 17:20

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

    24 янв 2018 в 17:34
    @SergeyGornostaev, и вообще лучше писать код сразу без ошибок, ага.
    24 янв 2018 в 18:44

    Указание типов как минимум позволяет раньше обнаружить ошибки.

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

    Отслеживать
    ответ дан 24 янв 2018 в 15:48
    tutankhamun tutankhamun
    11.3k 5 5 золотых знаков 25 25 серебряных знаков 40 40 бронзовых знаков
    насколько я знаю, Python не будет делать проверку типов даже в этом случае.
    24 янв 2018 в 15:53

    • python
    • функции
    • типы-данных
      Важное на Мете
    Связанные
    Похожие

    Подписаться на ленту

    Лента вопроса

    Для подписки на ленту скопируйте и вставьте эту ссылку в вашу программу для чтения RSS.

    Дизайн сайта / логотип © 2023 Stack Exchange Inc; пользовательские материалы лицензированы в соответствии с CC BY-SA . rev 2023.11.15.1019

    Нажимая «Принять все файлы cookie» вы соглашаетесь, что Stack Exchange может хранить файлы cookie на вашем устройстве и раскрывать информацию в соответствии с нашей Политикой в отношении файлов cookie.

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *