Главная страница
Навигация по странице:

  • : datetime.time

  • Подавление обработки кода в Mypy

  • type: ignore number = number.replace(3, ).replace(5, ) type: ignore

  • Аннотации типов для набора типов

  • Аннотации типов для списков, словарей и т. д.

  • List[str]

  • Обратное портирование аннотаций типов

  • Чистыйкод дляпродолжающи х


    Скачать 7.85 Mb.
    НазваниеЧистыйкод дляпродолжающи х
    Дата13.05.2023
    Размер7.85 Mb.
    Формат файлаpdf
    Имя файлаPython_Chisty_kod_dlya_prodolzhayuschikh_2022_El_Sveygart.pdf
    ТипДокументы
    #1127485
    страница24 из 40
    1   ...   20   21   22   23   24   25   26   27   ...   40
    : int) -> str:
    if number % 2 == 1:
    return 'An odd number. '
    elif number == 42:
    return 'The answer. '
    else:
    return 'Yes, that is a number. '
    myLuckyNumber: int = 42
    print(describeNumber(myLuckyNumber))
    Как видите, для параметров или переменных аннотация типа использует двоеточие для отделения имени от типа, тогда как для возвращаемых значений закрывающая круглая скобка команды def отделяется от типа стрелкой (
    ->
    ). Аннотации типов

    Аннотации типов
    227
    функции describeNumber()
    показывают, что функция получает целое число в па- раметре number и возвращает строковое значение.
    Если вы используете аннотации типов, вам не нужно применять их к каждому зна- чению данных в программе. Вместо этого можно воспользоваться методом посте-
    пенной типизации, сочетающим гибкость динамической типизации с безо пасностью статической типизации: аннотации типов включаются только для некоторых пере- менных, параметров и возвращаемых значений. Но чем больше аннотаций типов появляется в вашей программе, тем больше информации получат средства стати- ческого анализа кода для выявления потенциальных ошибок в вашей программе.
    Обратите внимание: в этом примере имена заданных типов совпадают с именами функций-конструкторов int()
    и str()
    . В Python термины «класс», «тип» и «тип данных» имеют одинаковый смысл. Для любых экземпляров, созданных на основе классов, имя класса используется как его тип:
    import datetime noon: datetime.time = datetime.time(12, 0, 0)

    class CatTail:
    def __init__(self, length: int, color: str) -> None:
    self.length = length self.color = color zophieTail: CatTail = CatTail(29, 'grey')

    Переменная noon снабжена аннотацией типа datetime.time

    , потому что это объект time
    (определенный в модуле datetime
    ). Аналогичным образом объект zophieTail снабжен аннотацией типа
    CatTail

    , потому что это объект класса
    CatTail
    , создан- ного командой class
    . Аннотации типов автоматически распространяются на все субклассы заданного типа. Например, переменной с аннотацией типа dict можно присвоить не только любое значение словаря, но и любое из значений collections.
    OrderedDict и collections.defaultdict
    , потому что эти классы являются субклас- сами dict
    . О субклассах мы более подробно поговорим в главе 16.
    Средствам статической проверки типов не обязательно нужны аннотации типов для переменных. Дело в том, что средства статической проверки типов выполняют автоматическое определение типа на основании первой команды присваивания переменной. Например, по строке spam
    =
    42
    система проверки типов может автома- тически определить, что переменная spam должна иметь аннотацию типа int
    . Тем не менее я все равно рекомендую включать аннотации типов. Будущий переход к типу float
    , как в команде spam
    =
    42.0
    , также изменит автоматически определяемый тип, что может противоречить вашим намерениям. Лучше заставить программиста изменить аннотацию типа при изменении значения, чтобы он подтвердил, что из- менение было внесено намеренно, а не случайно.

    228
    Глава 11.Комментарии, doc-строки и аннотации типов
    Статические анализаторы
    Хотя Python поддерживает синтаксис аннотаций типов, интерпретатор Python полностью их игнорирует. Если вы запустите программу Python, которая передает функции переменную с неправильным типом, Python будет вести себя так, словно аннотации типа не существует. Иначе говоря, аннотации типов не заставляют ин- терпретатор Python выполнять какую-либо проверку типов на стадии выполнения.
    Аннотации типов существуют только для средств статической проверки типов, которые анализируют код до запуска программы, а не во время выполнения.
    Эти средства называются средствами статического анализа, потому что они ана- лизируют исходный код до запуска программы, тогда как средства динамического анализа работают с уже запущенными программами. (В данном случае термины
    «статический» и «динамический» относятся к тому, выполняется ли программа, но под терминами «статическая типизация» и «динамическая типизация» понимается способ объявления типов данных переменных и функций. Python является языком с динамической типизацией, для которого были написаны средства статического анализа — такие как Mypy.)
    Установка и запуск Mypy
    Хотя у Python нет официальных средств проверки типов, из сторонних разработок в настоящее время наибольшей популярностью пользуется Mypy. Чтобы установить
    Mypy с помощью pip
    , выполните следующую команду:
    python –m pip install –user mypy
    В macOS и Linux выполните команду python3
    вместо python
    . Среди других популяр- ных систем проверки типов можно выделить Pyright (Microsoft), Pyre (Facebook) и Pytype (Google).
    Чтобы запустить программу проверки типов, откройте окно командной строки или терминала и выполните команду python
    -m mypy
    (чтобы запустить модуль как приложение) с именем проверяемого файла с кодом Python. В следующем примере проверяется код программы из файла с именем example.py
    :
    C:\Users\Al\Desktop>python –m mypy example.py
    Incompatible types in assignment (expression has type "float", variable has type "int")
    Found 1 error in 1 file (checked 1 source file)
    Программа не выводит ничего, если ошибки не найдены, и выводит сообщения об ошибках в противном случае. В файле example.py проблема обнаруживается в строке 171, потому что переменная с именем spam имеет аннотацию типа int
    , но

    Аннотации типов
    229
    ей присваивается значение float
    . Это присваивание способно привести к ошибке, и к нему стоит присмотреться. Некоторые сообщения об ошибках трудно понять с первого взгляда. В сообщениях Mypy могут упоминаться многочисленные воз- можные ошибки — слишком многочисленные, чтобы перечислять их здесь. Чтобы понять, что означает та или иная ошибка, проще всего поискать информацию в интернете.
    Запускать Mypy из командной строки при каждом изменении кода неэффективно.
    Чтобы пользоваться средствами проверки типов было удобнее, необходимо настро- ить IDE или текстовый редактор так, чтобы эти средства выполнялись в фоновом режиме. В этом случае редактор будет постоянно запускать Mypy при вводе кода, а затем выводить найденные ошибки в редакторе. На рис. 11.1 изображена ошибка из предыдущего примера в текстовом редакторе Sublime Text.
    Рис. 11.1. Ошибки Mypy в текстовом редакторе Sublime Text
    Конкретная последовательность действий по настройке IDE или текстового редак- тора для работы с Mypy зависит от того, в каком редакторе или IDE вы работаете.
    Инструкции можно найти в интернете — используйте условие поиска «<ваша IDE>
    Mypy настройка» (« Mypy configure»), «<ваша IDE> аннотации типов настройка» (« type hints setup») или что-нибудь в этом роде. Если все попытки оказались безуспешными, вы всегда можете запустить Mypy из окна ко- мандной строки или терминала.
    Подавление обработки кода в Mypy
    Представьте, что вы написали блок кода, для которого по какой-то причине вы не получаете предупреждения, относящиеся к аннотациям типов. С точки зрения средств статического анализа в строке вроде бы используется неправильный тип, но вы уверены, что во время выполнения эта строка будет работать правильно.
    Чтобы подавить любые предупреждения о типах, добавьте комментарий
    #
    type:
    ignore в конец строки. Пример:

    230
    Глава 11.Комментарии, doc-строки и аннотации типов def removeThreesAndFives(number: int) -> int:
    number = str(number) # type: ignore
    number = number.replace('3', '').replace('5', '') # type: ignore
    return int(number)
    Чтобы удалить из целого числа, передаваемого removeThreesAndFives()
    , все циф- ры 3 и 5, мы временно преобразуем целочисленную переменную в строку. Из-за этого программа проверки типов выдает предупреждения о двух первых строках функции, поэтому в эти строки добавляются аннотации типов
    #
    type:
    ignore для подавления предупреждений.
    Пользуйтесь директивами
    #
    type:
    ignore осмотрительно. Игнорирование преду- преждений от средств проверки типов открывает возможности для проникновения ошибок в ваш код. Код почти всегда можно переписать так, чтобы предупреждения не выдавались. Например, если создать новую переменную командой numberAsStr
    =
    str(number)
    или заменить все три строки кода одной строкой return int(str(number.
    replace('3',
    '').replace('5',
    '')))
    , можно избежать повторного использования переменной number для разных типов. Не следует подавлять предупреждения, из- меняя аннотацию типа для этого параметра на
    Union[int,
    str]
    , потому что этот параметр предназначен только для целых чисел.
    Аннотации типов для набора типов
    Переменные, параметры и возвращаемые значения Python могут принимать разные типы данных. Чтобы учесть эту возможность в программе, следует задать аннотации типов с несколькими типами; для этого надо импортировать
    Union из встроенного модуля typing
    . Набор допустимых типов задается в квадратных скобках после имени класса
    Union
    :
    from typing import Union spam: Union[int, str, float] = 42
    spam = 'hello'
    spam = 3.14
    В этом примере аннотация
    Union[int,
    str,
    float]
    указывает, что переменной spam может быть присвоено целое число, строка или число с плавающей точкой. Обра- тите внимание: лучше использовать форму команды импортирования from typing import
    X вместо import typing
    , а затем последовательно использовать развернутую форму typing.
    X для аннотаций типов во всей программе.
    Можно указать несколько типов данных в ситуациях, когда переменная или воз- вращаемое значение могут принимать значение
    None в дополнение к другому типу. Чтобы включить
    NoneType
    (тип значения
    None
    ) в аннотацию типа, укажите в квадратных скобках
    None вместо
    NoneType
    . (Формально
    NoneType не является встроенным идентификатором, каким является int или str
    .)

    Аннотации типов
    231
    Еще лучше вместо
    Union[str,
    None]
    импортировать
    Optional из модуля typing и использовать запись
    Optional[str]
    . Эта аннотация типа означает, что функция или метод может вернуть
    None вместо значения ожидаемого типа. Пример:
    from typing import Optional lastName: Optional[str] = None lastName = 'Sweigart'
    Здесь переменной lastName может быть присвоено значение str или
    None
    . Тем не менее к использованию
    Union и
    Optional стоит подходить осмотрительно. Чем меньше типов допускают ваши переменные и функции, тем проще будет ваш код, а в простом коде реже возникают ошибки, чем в сложном. Вспомните тезис «Дзен
    Python»: простое лучше, чем сложное. Если функция возвращает
    None как признак ошибки, рассмотрите возможность замены кода ошибки исключением (см. раздел
    «Выдача исключений и возвращение кодов ошибок», с. 214).
    Чтобы указать, что переменная, параметр или возвращаемое значение может иметь любой тип данных, используйте аннотацию типа
    Any
    (также из модуля typing
    ):
    from typing import Any import datetime spam: Any = 42
    spam = datetime.date.today()
    spam = True
    В этом примере аннотация типа
    Any позволяет вам присвоить переменной spam значение любого типа данных — например, int
    , datetime.date или bool
    . Также в качестве аннотации типа можно использовать object
    , потому что этот класс яв- ляется базовым для всех типов данных Python. Тем не менее аннотация типа
    Any лучше читается, чем object
    Any
    , как и
    Union и
    Optional
    , следует использовать осмотрительно. Назначив всем пере- менным, параметрам и возвращаемым значениям аннотацию типа
    Any
    , вы лишитесь преимуществ проверки типов, которые предоставляет статическая типизация. Разница между аннотацией типа
    Any и отсутствием аннотации состоит в том, что
    Any явно со- общает, что переменная или функция принимает значения любого типа, тогда как от- сутствие аннотации означает, что переменная или функция пока еще не аннотированы.
    Аннотации типов для списков, словарей и т. д.
    Списки, словари, кортежи, множества и другие контейнерные типы данных могут содержать другие значения. Если вы укажете список (
    list
    ) как аннотацию типа для переменной, эта переменная должна содержать список, но тот в свою очередь может содержать значения произвольного типа. Следующий код не вызовет никаких протестов у программы проверки типов:
    spam: list = [42, 'hello', 3.14, True]

    232
    Глава 11.Комментарии, doc-строки и аннотации типов
    Чтобы объявить типы данных значений, хранящихся в списке, используйте анно- тацию типа
    List модуля typing
    . Обратите внимание:
    List начинается с буквы
    L
    в верхнем регистре, что отличает ее от типа данных list
    :
    from typing import List, Union catNames: List[str] = ['Zophie', 'Simon', 'Pooka', 'Theodore']

    numbers: List[Union[int, float]] = [42, 3.14, 99.9, 86]

    В этом примере переменная catNames содержит список строк, поэтому после импортирования
    List из модуля typing мы задаем аннотацию типа
    List[str]

    Система проверки типов перехватывает все вызовы методов append()
    или insert()
    или любого другого кода, который помещает в список значения, не являющиеся строками. Если список должен содержать данные разных типов, используйте
    Union в аннотации типов. Например, список numbers может содержать целые числа и чис- ла с плавающей точкой, поэтому для него задается аннотация
    List[Union[int,
    float]]

    Модуль typing имеет отдельный псевдоним типа (type alias) для каждой разновид- ности контейнеров. Ниже перечислены псевдонимы для всех распространенных контейнерных типов Python:
    List для типа данных list
    ;
    Tuple для типа данных tuple
    ;
    Dict для типа данных словаря (
    dict
    );
    Set для типа данных set
    ;
    FrozenSet для типа данных frozenset
    ;
    Sequence для list
    , tuple и любых других типов данных последователь- ностей;
    Mapping для словарей (
    dict
    ), set
    , frozenset и любых других типов данных отображений;
    ByteString для типов данных bytes
    , bytearray и memoryview
    Полный перечень этих типов доступен по адресу https://docs.python.org/3/library/
    typing.html#classes-functions-and-decorators.
    Обратное портирование аннотаций типов
    Обратным портированием (backporting) называется процесс выделения некоторой функциональности из новой версии программного продукта и портирование ее

    Аннотации типов
    233
    (то есть адаптация и добавление) в более раннюю версию. Аннотации типов Python появились только в версии 3.5. Но в коде Python, который должен выполняться в версиях интерпретатора ниже 3.5, все равно можно использовать аннотации типов, размещая информацию о типах в комментариях. Для переменных используется встроенный комментарий после команды присваивания. Для функций и методов аннотации типов записываются в строке после команды def
    . Комментарий начи- нается с type:
    , а затем указывается тип данных. Пример кода с аннотациями типов в комментариях:
    from typing import List

    spam = 42 # type: int

    def sayHello():
    # type: () -> None

    """Doc-строка следует за комментарием с аннотацией типа."""
    print('Hello!')
    def addTwoNumbers(listOfNumbers, doubleTheSum):
    # type: (List[float], bool) -> float

    total = listOfNumbers[0] + listOfNumbers[1]
    if doubleTheSum:
    total *= 2
    return total
    Обратите внимание: даже если вы используете стиль аннотаций типов в ком- ментариях, все равно необходимо импортировать модуль typing

    , а также все псевдонимы типов, которые вы будете использовать в комментариях. В версиях до 3.5 стандартная библиотека не включала модуль typing
    , его следует установить отдельно следующей командой:
    python -m pip install --user typing
    В macOS и Linux используйте команду python3
    вместо python
    Чтобы связать переменную spam с целым типом, мы добавляем
    #
    type:
    int в ком- ментарий в конце строки

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

    . Если параметров несколько, разделите их запятыми в круглых скобках

    Аннотации типов в комментариях читаются хуже, чем просто аннотации типов, поэтому они используются только для кода, который может выполняться версиями
    Python до 3.5.

    234
    Глава 11.Комментарии, doc-строки и аннотации типов
    Итоги
    Программисты часто забывают о документировании своего кода. Но потратив не- много времени на добавление комментариев, doc-строк и аннотаций типов в ваш код, вы избежите временных затрат в будущем. Хорошо документированный код также проще сопровождать.
    Соблазнительно принять точку зрения, что комментарии и документация не важны или даже приносят вред при написании программ. (Такая позиция также избавляет программистов от работы по написанию документации — очень удобно.) Не обма- нывайте себя: хорошо написанная документация всегда экономит гораздо больше времени и усилий, чем требуется на ее создание. Программистам намного чаще приходится иметь дело со страницами невразумительного кода без комментариев, чем с избытком полезной информации.
    Хорошие комментарии предоставляют полезную, краткую и точную информацию тем, кому придется читать код позднее и разбираться в том, что код делает. Коммен- тарии должны объяснять намерения программиста и обобщать смысл небольших блоков кода, а не пересказывать очевидный смысл одной строки кода. Иногда в ком- ментариях содержится подробное описание информации, полученной и усвоенной программистом во время написания кода. В будущем эти ценные сведения избавят тех, кто занимается сопровождением кода, от горькой участи заново добывать ее, тратя время и силы.
    Doc-строки — разновидность комментариев, специфическая для Python, — пред- ставляют собой многострочные тексты, следующие непосредственно за командами class или def или расположенные в начале модуля. Средства документирования
    (например, встроенная функция Python help()
    ) могут извлекать doc-строки из кода, чтобы предоставить конкретные сведения о предназначении класса, функции или модуля.
    Аннотации типов, появившиеся в Python 3.5, дают Python механизм постепенной типизации. Постепенная типизация позволяет программисту пользоваться пре- имуществами статической типизации по определению типов без потери гибкости динамической типизации. Интерпретатор Python игнорирует аннотации типов, потому что в Python отсутствует проверка типов на стадии выполнения. Тем не менее средства статической разработки типов используют аннотации типов для анализа исходного кода до его выполнения. Средства проверки типов — такие как
    Mypy — следят за тем, чтобы переменным, передаваемым функциям, не присваива- лись недопустимые значения. Это экономит время и усилия за счет предотвращения самых разнообразных ошибок.

    1   ...   20   21   22   23   24   25   26   27   ...   40


    написать администратору сайта