Зачем вам: УТИНАЯ ТИПИЗАЦИЯ

Python — это язык с динамической типизацией. Однако в нем встроены утилиты вроде type hints для более строгой проверки типов. Неуклонное следование таким подсказкам мы вынуждены загромождать свой код. Но не каждый программист или Data Scientis знает, что Python поддерживает еще и утиную типизацию (duck typing) через протокол. Об этом мы расскажем сегодня.

Что такое утиная типизация (duck typing)

Утиная типизация (duck typing) — это направление в программировании, где в расчет в первую очередь идет на поведение и свойства объекта, а не на его тип.

NLP с Python

Код курса
PNLP
Ближайшая дата курса
28 ноября, 2022
Длительность обучения
40 ак.часов
Стоимость обучения
75 000 руб.

На практике это означает, что вы при написании функции должны волноваться только о поведении и/или атрибутах ее входных параметров, а не о их конкретных типах.

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

Протоколы для поддержки duck typing

Проанализируем следующий код с функцией на Python:

def calculate_windowed_avg(
        measurements: Union[List[TemperatureMeasurement], List[HumidityMeasurement]],
        window_size: timedelta,
        field_name: str
    ) -> Dict[datetime, float]:
    window_upper_bound = measurements[0].timestamp + window_size
    current_window = []
    window_averages = OrderedDict()
    for m in measurements:
        # various calculations happen here
        # based on the timestamp of each measurement
        ...
    return window_averages

Цель этой функции вычислить среднее для заданного поля field_name. На момент написания функция используется для классов TemperatureMeasurement и HumidityMeasurement, но очень вероятно, что захочется применять ее и для других типов измерений в будущем.

Если присмотреться ближе, то мы увидим, что объект обязательно должен иметь свое поле timestamp. Поэтому вместо указания этих длинных типов мы бы хотели, чтобы анализатор типов проверял наличие поля timestamp, а не тип.

Класс Protocol из модуля typing поможет сделать это. Так же как и в утиной типизации протокол лишь указывает на ожидаемое поведение или атрибуты без всякой заботы о типе.

Поглядите, как теперь более прилично и читаемо выглядит сигнатура с использование протокола:

from typing import Protocol, List, Dict
from datetime import datetime

class MeasurementLike(Protocol):
    timestamp: datetime

def calculate_windowed_avg(
        measurements: List[MeasurementLike],
        window_size: timedelta,
        field_name: str
    ) -> Dict[datetime, float]:
    window_upper_bound = measurements[0].timestamp + window_size

Теперь анализатор типов не знает точно, какой объект какого типа должен передаваться первым параметром, но он знает, что он должен иметь поле timestamp, потому что мы указали это в протоколе MeasurementLike.

В некотором роде протокол ведет себя как интерфейс в Java или TypeScript. Мы не вверяем желаемое поведение или атрибуты в тип, а в параметр функции. Это и есть демонстрация утиной типизации.

Протоколы и дженерики

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

Его можно использовать, когда вас не волнует тип параметра функции, поскольку он запротоколирован, но тип возвращаемого значения совпадает с типом входного параметра.

Например, функция для перевода измерений с использование TypeVar может выглядеть так:

from typing import Protocol, TypeVar
from datetime import datetime

class MeasurementLike(Protocol):
    timestamp: datetime

M = TypeVar('M', bound=MeasurementLike)

def measurement_as_timezone(measurement: M, tz: tzinfo) -> M:
    measurement.timestamp = measurement.timestamp.astimezone(tz)
    return measurement

Как видим, Python предоставляет большие возможности для разных видов типизации.

 

Еще больше о фишках написания читаемого кода вы узнаете на наших образовательных курсах в лицензированном учебном центре обучения и повышения квалификации руководителей и ИТ-специалистов (менеджеров, архитекторов, инженеров, администраторов, Data Scientist’ов и аналитиков Big Data) в Москве:

Источники
  1. Оригинал статьи

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

Поиск по сайту