Финальная аннотация и декоратор в python3.8
В выпуске Python 3.8 вскоре просто захотелось узнать разницу между финальным декоратором и аннотацией Final.
1 ответ
В Python 3.8 функция хинтинга типа Python (воплощенная typing
модуль) будет поддерживать маркировку имен как окончательных. Это задокументировано в PEP 591 - Добавление окончательного квалификатора к печати.
Это означает, что typing
Модуль получает два новых объекта:
-
typing.Final
печатная конструкция -
@typing.final()
декоратор
Чтобы быть открытым: сам язык Python не получает final
синтаксис или поддержка. Вышеуказанные объекты не изменяют работу Python, они представляют собой конструкции, которые просто документируют, что объект или ссылка должны считаться окончательными. Новые объекты можно легко перенести в более старые версии Python. typing-extensions
проект, который обеспечивает бэкпорты typing
функции от более поздних версий Python, уже включены эти объекты.
Их использование заключается в использовании средства проверки подсказок типа mypy для проверки того, что ваш проект правильно обрабатывает объекты, задокументированные как окончательные.
Их использование в остальном точно так же, как использование final
ключевое слово в Java: указать, что конкретная ссылка может быть назначена только один раз, что метод не может быть переопределен в подклассе или что определение класса не может быть разделено на подклассы.
Использовать
typing.Final
объект, чтобы пометить глобальный или атрибут как окончательный, документируя, что значение никогда не изменится, если назначено:GLOBAL_CONSTANT: Final[str] = "This is a constant value because it is final"
Использовать
@typing.final
декоратор, чтобы пометить метод как не подлежащий переопределению (подклассы не могут определить другую реализацию) или класс как не наследуемый (вы не можете создавать подклассы из класса):@final class FinalClass: """This class can't be inherited from""" class SomeClass: @final def final_method(self): """Subclasses can't define a different final_method implementation"""
Также см. Документацию mypy об их использовании, которая охватывает такие подробности относительно того, какие способы присвоения значения Final
Атрибут приемлем.
Демо-версия:
$ cat demo.py
from typing import final, Final
# FOO is marked final, can't assign another value to it
FOO: Final[int] = 42
class Foo:
@final
def spam(self) -> int:
"""A final method can't be overridden in a subclass"""
return 42
@final
class Bar:
"""A final class can't be subclassed"""
# Rule breaking section
FOO = 81
class Spam(Foo, Bar):
def spam(self) -> int:
return 17
if __name__ == '__main__':
print("FOO:", FOO)
print("Spam().spam():", Spam().spam())
$ python3.8 demo.py # Python will not throw errors here
FOO: 81
Spam().spam(): 17
$ mypy demo.py # only a type checker will
demo.py:17: error: Cannot assign to final name "FOO"
demo.py:19: error: Cannot inherit from final class "Bar"
demo.py:20: error: Cannot override final attribute "spam" (previously declared in base class "Foo")