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

  • Вызываемые объекты

  • Об образовательной программе Диджитализируй!

  • 27 мая 2022 1600

  • Типизированный_Python_для_профессиональной_разработки. Профессиональной разработки


    Скачать 3.38 Mb.
    НазваниеПрофессиональной разработки
    АнкорPython
    Дата15.12.2022
    Размер3.38 Mb.
    Формат файлаpdf
    Имя файлаТипизированный_Python_для_профессиональной_разработки.pdf
    ТипДокументы
    #847528
    страница5 из 5
    1   2   3   4   5
    Важно!
    По возможности вместо указания в типах list
    , dict и тп указывай классы,
    Sequence
    ,
    Mapping
    Во-первых, это позволит менять конкретные реализации, удовлетворяющие условию итерабельности, доступа по индексу или доступа по ключу соответственно, решение получится более гибким.
    Во-вторых, анализатор кода mypy будет лучше работать с такими типами данных
    ,
    что позволит избежать некоторых осложнений.
    Если от контейнера требуется итерабельность (чтобы поданным в контейнере можно было итерироваться, то есть проходить в цикле, то стоит указать, который гарантирует именно итерабельность, вместо того, чтобы указывать одни из возможных реализаций итерабельных контейнеров вроде list или tuple
    , несущих помимо собственно итерабельности и другие свойства.
    Если от контейнера требуется доступ по индексу, то стоит указать
    Sequence
    , а не одну из возможных реализаций вроде Наконец, если требуется доступ по ключу, то следует указать Пару слов стоит сказать про кортежи, если размер кортежа важен и мы хотим его прямо указать в типе, то это можно сделать так:
    Если количество элементов неизвестно — можно так typing import
    Mapping def smth
    (
    some_users
    :
    Mapping
    [
    str
    ,
    User
    ])
    ->
    None
    :
    print
    (
    some_users
    [
    "alex"
    ])
    smth
    ({
    "alex"
    :
    User
    (
    birthday
    =
    datetime fromisoformat
    (
    "1990-01-01"
    )),
    "petr"
    :
    User
    (
    birthday
    =
    datetime fromisoformat
    (
    "1988-10-23"
    ))
    })
    three_ints
    =
    tuple
    [
    int
    ,
    int
    ,
    int
    ]

    Дженерики
    Что если мы хотим написать обобщённую функцию, которая принимает на вход итерируемую структуру, то есть структуру, по которой можно итерироваться, и возвращает результат первой итерации?
    Как видите, типом данных в этой итерируемой структуре iterable могут быть любые данные, анаши в функции first говорят буквально, что функция принимает на вход итерабельную структуру данных, каждый элемент которой имеет тип
    T
    , и функция возвращает тот же тип
    T
    . Тип
    T
    при этом может быть любым.
    Это так называемые дженерики, то есть обобщённые типы.
    Причём имя
    T
    здесь это пример, он часто используется именно так,
    T
    , от Type, но название типа может быть и любым другим.
    Помимо дженериков можно сохранять отдельные типы для лучшей читаемости кода и подсказки читателю, что именно заданные здесь хранятся
    =
    tuple
    [
    int
    ,
    ...]
    from typing import
    TypeVar
    ,
    Iterable
    T
    =
    TypeVar
    (
    "T"
    )
    def first
    (
    iterable
    :
    Iterable
    [
    T
    ])
    ->
    T
    |
    None
    :
    for element in iterable
    :
    return element print
    (
    first
    ([
    "one"
    ,
    "two"
    ]))
    # one print
    (
    first
    ((
    100
    ,
    200
    )))
    # 200
    from dataclasses import dataclass
    Phone
    =
    str
    @dataclass class
    User
    :
    user_id
    :
    int phone
    :
    Phone
    Мы уже использовали это в коде приложения погоды, когда задавали псевдоним для градусов Цельсия.
    Вызываемые объекты
    Как известно функции в Python это обычные объекты, которые можно передавать в другие функции, возвращать из других функций и тп, поэтому для них тоже есть свой тип Здесь для аргумента operation функции process_operation проставлен тип, int], int]
    . Здесь
    [int, int]
    — это типы аргументов функции operation
    , получается, что у этой функции должно быть два аргумента и они оба должны иметь тип int
    . Последний int в определении типа
    Callable[[int, int], обозначает тип возвращаемого функцией значения файлы и работа с нетипизированными библиотеками

    Важно понимать, что type hinting работает не только для аргументов функций и возвращаемых значений. Мы можем просто создать переменную и указать ей тип:
    В таком сценарии это избыточно — IDE и статический анализатор кода итак видят,
    что в переменной book хранится значение типа str
    . Однако в таком сценарии get_user_phone
    (
    user
    :
    User
    )
    ->
    Phone
    :
    return user phone from typing import
    Callable def mysum
    (
    a
    :
    int
    ,
    b
    :
    int
    )
    ->
    int
    :
    return a
    +
    b def process_operation
    (
    operation
    :
    Callable
    [[
    int
    ,
    int
    ],
    int
    ],
    a
    :
    int
    ,
    b
    :
    int
    )
    ->
    int
    :
    return operation
    (
    a
    ,
    b
    )
    print
    (
    process_operation
    (
    mysum
    ,
    1
    ,
    5
    ))
    # Тополек мой в красной косынке
    функция поиска книги find_book_in_library может быть не нашей функцией, а функцией какой-то внешней библиотеки, которая не использует подсказки типов. То есть для функции может быть не проставлен тип возвращаемого значения. Чтобы и статический анализатор знали, что тип данных, который будет храниться в это именно str
    , можно таким образом подсказать инструментам о верном типе.
    Иногда это бывает очень полезно, когда библиотека не использует подсказки типов,
    а возвращаемый тип данных какой-то сложный и мы хотим, чтобы IDE и mypy нам помогали анализировать наш код и типы.
    В тоже время в Python существует механизм так называемых стаб-файлов, которые позволяют типизировать в том числе внешние библиотеки. Например, для django есть пакет в pip, который называется django-stubs
    . О стаб-файлах есть видео на канале Диджитализируй!.
    Если вы используете нетипизированную библиотеку — можно поискать готовые стаб файлы для не, чтобы воспользоваться преимуществами типизированного Подсказки типов нужны только в функциях?

    В чате Telegram канала задали отличный вопрос — подсказки типов имеет смысл ставить только для аргументов функций и возвращаемых значений или вообще для всех переменных?
    И действительно. Как лучше?
    В большинстве сценариев подсказок типов достаточно только для аргументов и результатов функций. Если в нашем коде все функции типизированы таким образом,
    то получается, что IDE и статический анализатор кода понимают тип любой переменной в коде и могут выполнять все проверки.
    Объявляя переменную, мы либо задаём её значение в явном виде (и тогда тип переменной равен типу значения):
    Здесь тип переменной age равен типу значения
    33
    , то есть int
    , а тип переменной user равен
    User book
    :
    str
    =
    Тополек мой в красной косынке
    =
    33
    user
    =
    Иннокентий
    Второй вариант создания переменной — присваивание ей значения, которое возвращается функцией:
    Если все функции в нашем коде типизированы, в том числе и функция get_user_by_username
    , то ив таких сценариях тип переменной очевиден. Какой тип данных функция возвращает, такой тип данных у переменной и будет.
    Получается, что если все функции, используемые в коде, типизированы, то как правило нет смысла проставлять типы для обычных переменных.
    Однако, иногда бывает так, что мы используем внешнюю библиотеку, функции которой нетипизированы. Если функция get_user_by_username в примере выше это функция внешней библиотеки иона нетипизирована, то IDE и статический анализатор кода не знают, какой тип данных вернёт эта функция и потому не знают,
    какой тип будет у переменной user
    . Тогда можно подсказать инструментам, явно указав тип:
    Теперь IDE и статический анализатор будут знать тип переменной и смогут выполнять все проверки. Отлично!
    Ещё один сценарий, при котором полезно задать переменной тип — когда мы инициализируем переменную пустым значением, но хотим указать, данные какого конкретно типа там будут.
    Например, в конструкторе класса мы инициализируем атрибут с начальным значением
    {}
    , то есть пустой словарь, но указываем, что в этом словаре ключами будут строки, значениями числа. То есть мы уточняем тип данных, сужаем его с просто словаря до словаря с конкретным типом ключей и значений
    =
    Иннокентий User
    =
    Иннокентий self
    _some_dict
    :
    dict
    [
    str
    ,
    int
    ]
    =
    {}
    def some_method
    (
    self
    ):
    self
    _some_dict
    [
    "some_key"
    ]
    =
    123
    # Всё ок по типам self
    _some_dict
    [
    123
    ]
    =
    "some_key"
    # Ошибка типов

    Резюме
    Грамотное использование type hinting и осознанный выбор классов отделяет код новичка от кода растущего профессионала. Пользуйся подсказками типов,
    продумывай структуру твоего приложения и используемые типы данных, и тогда твои решения будут красивыми, приятно читаемыми, легко поддерживаемыми и надёжными.
    Ты дочитал досюда и разобрался с материалом Отлично, молодец Думаю, тебе стоит прислать нам резюме на почту join@to.digital

    Контакты
    У нас много хороших материалов в YouTube, если вдруг ты ещё не подписан —
    YouTube канал Диджитализируй!
    Много оперативной и текстовой полезной информации — в
    Telegram канале
    !
    Также, конечно, есть
    VK группа и
    Дзен
    Об образовательной программе Диджитализируй!
    Сейчас готовится к перезапуску курс Основы компьютерных и веб-технологий с. Курс — отличный, на Stepik Awards был признан лучший платным курсом. Подписывайся, чтобы не пропустить старт. Новое издание курса будет на больше и полезнее!
    А если ты читаешь это позднее июня 2022, то вполне вероятно, что курс уже вышел.
    Беги по ссылке
    Здесь приведены редакции этой книги и изменения в каждой. Последнюю,
    актуальную версию книги можно скачать здесь t.me/t0digital/151
    27 мая 2022 1600 Изменения:
    Обновлена глава о Добавлена информация о pyright анализаторе кода в дополнение к Добавлены рекомендации в главу Контейнеры — Iterable, Sequence, Mapping и другие»
    Исправлены найденные опечатки мая 2022 0400 Изменения:
    Добавилась информация о протоколах typing.Protocol в главе об интерфейсах
    Добавилась информация о параметрах датаклассов slots и Добавлен пример в главу Интерпретатор не проверяет подсказки типов»
    Расширена глава о
    Enum
    , добавлено про наследование от Расширена глава Подсказки типов нужны только в функциях?»
    Исправлены найденные опечатки мая 2022 Первая версия книги
    1   2   3   4   5


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