Я устал от неправильного внедрения людей, а не в соответствии с интерфейсом базового класса, например, добавление новых позиционных аргументов, не определенных в методе базового класса. Обычно это происходило, когда у вас есть шаблон плагина, где существует множественная бэкэнд или реализация для заданной функциональности. И каждый бэкэнд был разработан отдельной командой/разработчиком.
Или необходимость записать тесты, чтобы убедиться, что правильные параметры передавались для функции. Тесты должны быть записаны, чтобы проверить логику, а не синтаксис языка или семантику.
Первое, что я хочу, – это то, что может проверить подпись метода, это в соответствии с спецификацией базового класса.
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”