Многие языки, такие как Java
и PHP
Поделитесь концепцией Финал
объекты. Финал
Сущность – это то, что не может быть изменено.
У нас не было этой функции в Python
Отказ Пока два события не произошло недавно:
- Я выпустил
Финальный класс
упаковка Python
Основная команда выпустил ОфициальныйФинал
Поддержка вНабрав
модуль
Теперь у нас действительно есть новый блестящий Языковая особенность! Давайте копать, как это работает и почему это так удивительно.
Объявляя константы
Прежде всего, вам нужно будет установить Marpy
и type_extensions
:
» pip install mypy typing_extensions
Тогда мы можем начать использовать его:
from typing_extensions import Final DAYS_IN_A_WEEK: Final = 7
Вот и все! Но что произойдет, если мы попытаемся изменить эту константу?
from typing_extensions import Final DAYS_IN_A_WEEK: Final = 7 DAYS_IN_A_WEEK = 8 # I really want more days in a week!
Правда ничего. Это просто старый добрый Python
Где вы можете сделать странные вещи без окупаемости. Это просто не волнует тип аннотации.
Вся магия происходит только тогда, когда мы бежим Marpy
Тип проверки:
» mypy --python-version=3.6 --strict week.py week.py:4: error: Cannot assign to final name "DAYS_IN_A_WEEK"
Груз! У нас здесь постоян!
Посмотрите, как Финал
Тип сделки с базовыми типами. Вам не нужно вручную рассказать тип проверки типа, какой тип на самом деле. Это будет понять это все сам по себе. Другими словами, тип проверки будет знать, что Days_in_a_week
это int
Отказ
Интерфейсы
И это выходит за рамки только объявления констант. Вы можете объявить свои интерфейсные части, такие как атрибуты и методы, которые не должны быть изменены:
from typing_extensions import Final, final class BaseAPIDeclaration(object): namespace: Final = 'api' @final def resolve(self) -> dict: return {'namespace': self.namespace, 'base': True}
Теперь все подклассы этого воображаемого класса не смогут переопределить оба пространство имен
и разрешать ()
Отказ Но, давайте постараемся взломать их, чтобы увидеть, что произойдет:
class ConcreteAPI(BaseAPIDeclaration): namespace = 'custom-api' def resolve(self) -> dict: return {'hacking': True}
Marpy
верну нас вверх. Вот что будет выглядеть вывод:
» mypy --python-version=3.6 --strict api.py api.py:12: error: Cannot assign to final name "namespace" api.py:14: error: Cannot override final attribute "resolve" (previously declared in base class "BaseAPIDeclaration")
Классы
И даже классы могут быть Финал
Отказ Таким образом, мы можем явно запретить классы подкласса, не предназначенные для подклассов:
from typing_extensions import final @final class HRBusinessUnit(AbstractBusinessUnit): def grant_permissions(self) -> None: self.api.do_some_hr_stuff()
Что делает @final
Декоратор приносит тебя? Уверенность, что ничто не сломает этот договор:
class SubHRBusinessUnit(HRBusinessUnit): def grant_permissions(self) -> None: self.api.do_some_it_stuff()
Этот код сделает Marpy
Вполне несчастные (пожалуйста, не злоупотребляйте роботами!):
» mypy --python-version=3.6 --strict units.py units.py:9: error: Cannot inherit from final class "HRBusinessUnit"
Теперь мы можем рассуждать о том, почему вы должны использовать его в вашем проекте.
Вывод
Создание новых ограничений полезно для вас: он делает ваш кодовый очиститель, более читаемый и увеличивает его качество.
Сильные стороны:
- Из определения ясно, что является постоянной или конкретной реализацией, а что нет
- У наших пользователей будут строгие границы API которые не могут быть нарушены
- Мы можем построить закрытые системы, которые не терпимы к нарушению правил
- Легче понять, что происходит в вашем приложении
- Это усиливает Состав по наследству , что является известной лучшей практикой
Слабые точки: нет! Написать комментарий, если вы сможете найти какие-либо недостатки.
Используйте типы, создавайте приятные API, продолжайте взлом!
Оригинал: “https://dev.to/wemake-services/1-minute-guide-to-real-constants-in-python-2bpk”