相信很多编程高手都在某些类库的源码中见过
一个神奇的装饰器 final
通常用在这种地方
@final
class A:
...
或者
@final
def some_method():
...
然而我们打开是看傻眼了, 它的实现是这个样子
def final(f):
"""A decorator to indicate final methods and final classes.
Use this decorator to indicate to type checkers that the decorated
method cannot be overridden, and decorated class cannot be subclassed.
For example:
class Base:
@final
def done(self) -> None:
...
class Sub(Base):
def done(self) -> None: # Error reported by type checker
...
@final
class Leaf:
...
class Other(Leaf): # Error reported by type checker
...
There is no runtime checking of these properties.
"""
return f
除掉注释,什么都没做,这可能是世界上最简单的装饰器了,社区有一个称呼——no-op
这就相当于——
“我在这里写个大大的警示牌:请不要继承/重写我!
聪明人(和类型检查器)会听话,不聪明的人……Python 才不管呢,爱咋咋地。”
因为运行时,解释器根本不管这个 @final标记,对性能的影响也是微乎其微,因此final是作为一个警示牌的作用,在控制代码质量方面却很有影响
总结
final纯粹是给人类和类型检查器之间的契约,作用可以总结为这几点:
- 文档作用极强:看到 @final 就立刻知道“作者明确不希望你继承/重写”
- 防御性编程:在开发阶段就能把误继承、误重写掐死在摇篮里(CI 里 mypy 一跑就红)
- 重构安全:你把一个方法标记为 @final 后,以后别人(包括未来的你)想重写它时,IDE/检查器立刻报警,避免破坏原有逻辑
- 团队编码规范:很多大厂(Google、Instagram、Dropbox 等)的 Python 代码库都强制要求:DTO、Event、Config、ValueObject 一律加 @final