Рубрики
Без рубрики

Первый взгляд на протоколы Python (PEP 544)

Мне очень нравятся типовые подсказки, добавленные в Python 3.5, PEP 484, но каким -то образом я полностью пропустил PEP 544 – Pro … Tagged Python, Typechecking, программирование, кодирование.

Мне очень нравятся типовые подсказки, добавленные в Python 3.5, PEP 484, но каким -то образом я полностью пропустил PEP 544 – Протоколы: структурное подтип (статическая набор уток) . Протоколы были добавлены в Python 3.8, который, хотя он является текущей стабильной версией Python, почти год. Мы очень заканчиваемся на Python 3.9, релиз запланирован на пятый октябрь. В этом посте я впервые посмотрю на протоколы и то, как они работают с линином, используя Pylance в VS -коде.

Название PEP говорит Статическая утка печатает , что на самом деле является действительно хорошим описанием протоколов. Они позволяют вам определить интерфейс/шаблон, который должен выполнять объект, и если он, как говорят, является экземпляром протокола. Протоколы просто проверяются инструментами проверки типов и не применяются во время выполнения.

Sidenote: Для других, таких как я, которые играли с TypeScript (TS), протоколы действительно похожи на интерфейсы TS.

Я думаю, что самый простой способ понять протоколы – написать какой -то код, так что давайте погрузимся. Сначала мы определяем протокол Печатный :

from abc import abstractmethod
from typing import Protocol
class Printable(Protocol):
    @abstractmethod
    def print(self) -> None:
        raise NotImplementedError

Как видите, это класс, который наследует от класса Протокол Анкет У него есть один абстрактный метод Печать , который не берет аргументов и не возвращает ни одного. Обратите внимание, что в Python Нет возвращается, если функция не имеет оператора возврата.

Давайте определим класс, который выполняет этот протокол, и класс, который нет.

class MyPrintable:
    def print(self) -> None:
        print("Hello DEV!")

class NonPrintable:
    pass

Я использую код Visual Studio с Пиленок плагин. С пиленом вы можете использовать настройку Python.Analysis.TypecheckingMode . Это может быть отключенным, базовым или строгим; Я сейчас работаю с помощью базовый Анкет Скриншоты в этом посте используют эти настройки.

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

def simple_print(printable: Printable):
    printable.print()

Если мы передаем экземпляр MyPrintable, а затем не отпечатывается на функцию, это то, что появляется в редакторе.

Неприемный подчеркнут, и, если наказано, мы увидим это сообщение об ошибке:

И Mypy, и Pylance жалуются на то, насколько неприемный не выполняется протокол для печати. Это также означает, что объект MyPrintable правильно идентифицируется как выполнение протокола, не требуется наследование.

Sidenote: Я действительно наслаждаюсь пиленом, посмотрите на это сообщение об ошибке! Это просто фантастика!

Как я упоминал ранее, во время выполнения эта информация не используется. Тем не менее, программа, конечно, сбой, когда мы попытаемся позвонить в Печать -Мете на непричатом, поскольку его не существует.

В Python мы обычно используем Isinstance Функция, чтобы проверить, является ли объект экземпляром класса. Это работает и для протоколов? Я думаю, мы должны попробовать это и сделать это, я написал это:

def my_print(printable: Printable):
    if isinstance(printable, Printable):
        print("It is a printable!")
        printable.print()
    else:
        print("boooo, not a printable")

my_print(MyPrintable())
my_print(NonPrintable())

Теперь давайте посмотрим, что Пиленс думает об этом.

Ну, это не очень хорошо.

Итак, протокол не работает в Isinstance Проверьте. Давайте также посмотрим на другое сообщение об ошибке.

Интересно, поэтому проверить экземпляр на протоколе, используя Isinstance , нам нужно украсить наш протокол с помощью @runtime_checkable Анкет Обратите внимание, что вам будет проинформирована об этом, если вы также запустите код. Это сообщит об этой ошибке во время выполнения:

TypeError: Instance and class checks can only be used with @runtime_checkable protocols

В соответствии с ошибкой все, что нам нужно сделать, это добавить декоратор в класс, например, это:

@runtime_checkable 
class Printable(Protocol):
    @abstractmethod
    def print(self) -> None:
        raise NotImplementedError

Теперь запуск того же кода покажет этот вывод:

It is a printable!
Hello DEV!
boooo, not a printable

PEP544 дает нам протоколы, которые позволяют нам определить, какие требования функция или класс предназначены для параметра. Еще более интересно, это позволяет нам делать это без использования наследования, в то же время работая с Isinstance Анкет

Это был лишь первый взгляд на протоколы, и есть гораздо больше, чтобы исследовать. Например, они поддерживают определение переменных экземпляра и класса. Протоколы также могут быть общими, расширенными и объединенными. Это добавляет действительно интересный инструмент для написания Python, проверенного типа, и будет интересно экспериментировать с ним в будущем проекте.

Оригинал: “https://dev.to/fronkan/a-first-look-at-python-protocols-pep-544-24bn”