python3.8中的最终注释和装饰器

Rou*_*han -2 type-hinting python-3.x python-3.8

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

Mar*_*ers 9

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

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

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

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

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

  • 使用typing.Final对象将全局或属性标记为 final,记录该值一旦分配给就永远不会改变:

    GLOBAL_CONSTANT: Final[str] = "This is a constant value because it is final"
    
    Run Code Online (Sandbox Code Playgroud)
  • 使用@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"""
    
    Run Code Online (Sandbox Code Playgroud)

另请参阅有关它们的使用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")
Run Code Online (Sandbox Code Playgroud)