Мне очень нравятся типовые подсказки, добавленные в 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”