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

Mypy: Быстрый взгляд на проверку статического типа в Python

Mypy – это экспериментальная дополнительная проверка статического типа для Python, которая направлена на то, чтобы объединить преимущества динамического (или «утки») типирования и статического типирования .. Tagged с Python, Mypy, типами, плагинами.

Я устал от неправильного внедрения людей, а не в соответствии с интерфейсом базового класса, например, добавление новых позиционных аргументов, не определенных в методе базового класса. Обычно это происходило, когда у вас есть шаблон плагина, где существует множественная бэкэнд или реализация для заданной функциональности. И каждый бэкэнд был разработан отдельной командой/разработчиком.

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

Первое, что я хочу, – это то, что может проверить подпись метода, это в соответствии с спецификацией базового класса.

https://medium.com/@ageitgey/learn-how-to-use-static-type-checking-in-python-3-6-in-10-minutes-12c86d72677b

Дайте увидеть следующий простой пример:-

class A():
    def __init__(self, x):
        self.x = x

    def send(self, msg):
        pass

class B(A):
    def send(self, msg):
        return True

Проблема с вышеупомянутым кодом заключается в том, что другой разработчик (или команда) может реализовать Send () Метод в B класс таким образом, что это несовместимо с другим подклассом. Например добавив дополнительный параметр:-

class A():
    def __init__(self, x):
        self.x = x

    def send(self, msg):
        pass

class B(A):
    def send(self, msg, extra):
        return True

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

import abc

class A(abc.ABC):
    def __init__(self, x: int) -> None:
        self.x = x     # Attribute x of type int

    @abc.abstractmethod
    def send(self, msg: str) -> bool:
        pass

class B(A):
    def send(self, msg: str) -> bool:
        return True

b = B(1)
b.x = 2       # OK
b.send('hello')

Теперь, если кто -то попытается реализовать B добавив дополнительный параметр в Send () В такие как:-

import abc

class A(abc.ABC):
    def __init__(self, x: int) -> None:
        self.x = x     # Attribute x of type int

    @abc.abstractmethod
    def send(self, msg: str) -> bool:
        pass

class B(A):
    def send(self, msg: str, extra: str) -> bool:
        return True

b = B(1)
b.x = 2       # OK
b.send('hello', 'extra')

Запуск этого через Mypy даст нам ошибку:-

base.py:12: error: Signature of "send" incompatible with supertype "A"

Хорошо, теперь мы решили проблему, упомянутая в начале этой статьи.

Другой общей проблемой является несоответствие в возвратной стоимости. Например:-

import abc

class A(abc.ABC):
    def __init__(self, x: int) -> None:
        self.x = x     # Attribute x of type int

    @abc.abstractmethod
    def send(self, msg: str) -> bool:
        pass

class B(A):
    def send(self, msg: str) -> bool:
        return 'hello'

b = B(1)
b.x = 2       # OK
b.send('hello')

Выше, метод Send () В классе A был аннотирован, чтобы вернуть логическое, но с B.send () вернуть строку, Mypy будет жаловаться:-

base.py:13: error: Incompatible return value type (got "str", expected "bool")

Я вижу некоторый потенциал в Mypy здесь. Это может быть хорошим комплиментом нашему набору тестов Таким образом, нам не нужно писать тесты для некоторых случаев, которые могут быть пойманы компилятором (если у нас есть). Но, к сожалению, Mypy делает Еще не поддерживает пакет с именами И мы много используем пакет с именами.

Еще одна проблема, с которой мы столкнулись, была с Buildout. Чтобы дать подсказку типа для стандартной библиотеки (которая в большинстве случаев еще не имеет аннотации), Mypy предоставляет библиотеку затенения под названием Typeshed. Скрипт наращивания определяет это собственное sys.path Но Мипи игнорирует sys.path Поскольку сначала он должен посмотреть в типографии, это означает, что все пути, установленные настройкой в нашем сценарии, не пригодны для использования. Мы должны указать это как Mypypath Но это все еще не сработало, поэтому я просто сдался.

Оригинал: “https://dev.to/k4ml/i-started-to-like-mypy-but–4g02”