在 Python 3.8 中,Python 类型提示功能(体现为typing module https://docs.python.org/3/library/typing.html) 将支持将名称标记为final。这记录在PEP 591 –在输入中添加最终限定符 https://www.python.org/dev/peps/pep-0591/.
这意味着typing
模块获得两个新对象:
- The typing.Final打字构造 https://docs.python.org/3.8/library/typing.html#typing.Final
- The @typing.final()装饰者 https://docs.python.org/3.8/library/typing.html#typing.final.
预先:Python语言本身并没有获得final
语法或支持。上述对象不会改变 Python 的工作方式,它们的构造是仅仅记录对象或引用被视为最终的。新对象可以轻松向后移植到较旧的 Python 版本。这typing-extensions project https://pypi.org/project/typing-extensions/,它提供了向后移植typing
从较新的 Python 版本到较早的 Python 版本的功能,已经包含这些对象 https://github.com/python/typing/commit/c6c7dfdd4b999a2bbd46d120adeacc504d74e044.
它们的用途在于使用类型提示checker like mypy https://docs.python.org/3.8/library/typing.html#typing.final检查您的项目是否正确地将记录的对象视为最终对象。
它们的使用在其他方面与finalJava中的关键字 https://en.wikipedia.org/wiki/Final_(Java):声明特定引用只能分配给once,方法不能在子类中重写,或者类定义不能被子类化。
-
Use the typing.Final
对象将全局或属性标记为最终,记录该值一旦分配给就永远不会改变:
GLOBAL_CONSTANT: Final[str] = "This is a constant value because it is final"
-
Use the @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 的使用文档 https://mypy.readthedocs.io/en/latest/final_attrs.html,其中涵盖了如何分配 a 值的详细信息Final
属性是可以接受的。
Demo:
$ 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")