Финальная аннотация и декоратор в python3.8

В выпуске Python 3.8 вскоре просто захотелось узнать разницу между финальным декоратором и аннотацией Final.

1 ответ

В Python 3.8 функция хинтинга типа Python (воплощенная typing модуль) будет поддерживать маркировку имен как окончательных. Это задокументировано в PEP 591 - Добавление окончательного квалификатора к печати.

Это означает, что typing Модуль получает два новых объекта:

Чтобы быть открытым: сам язык 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")
Другие вопросы по тегам