首页 > 解决方案 > python3.8中的final注解和装饰器

问题描述

由于 Python 3.8 即将发布,只是想知道The final decorator 和 The Final annotation之间的区别。

标签: python-3.xtype-hintingpython-3.8

解决方案


在 Python 3.8 中,Python 类型提示功能(由typingmodule体现)将支持将名称标记为final。这在PEP 591 –添加最终限定符到 typing中记录。

这意味着该typing模块获得了两个新对象:

提前说明:Python 语言本身没有获得final语法或支持。上面的对象不会改变 Python 的工作方式,它们只是记录一个对象或引用被认为是最终的构造。新对象可以轻松地向后移植到较旧的 Python 版本。该typing-extensions项目typing提供从后来的 Python 版本到早期版本的功能的反向移植,已经包含了这些对象

它们的用途在于使用像mypy这样的类型提示检查器来检查您的项目是否正确地将记录的对象视为最终对象。

它们的使用与finalJava 中的关键字完全相同:声明特定引用只能分配给一次,不能在子类中覆盖方法,或者不能将类定义子类化。

  • 使用该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")

推荐阅读