Python Final 是否真的不可变?

9次阅读

python 的 final 仅为类型提示,无运行时强制不可变性;它仅在 mypy 等静态检查中报错,解释器忽略;Final 不阻止可变对象内容修改,真正不可变需用 tuple、frozen dataclass 等机制。

Python Final 是否真的不可变?

Python 中的 final 并不是语言内置的“不可变”机制,它本身不提供运行时强制的不可变性,而只是一个类型提示和开发约定。

Final 是类型检查层面的标记

typing.Final 仅在静态类型检查(如 mypy)中起作用。它告诉类型检查器:“这个变量/属性不应被重新赋值”。但 Python 解释器完全忽略它,运行时可以随意修改:

  • 例如:from typing import Final
    a: Final[int] = 42
    a = 100 # mypy 报错,但 Python 运行正常,a 变为 100

类属性与实例属性的行为不同

Final 对类变量和实例变量的约束力度一致,但实际效果取决于使用方式:

  • 标注为 Final 的类变量(如 MAX_SIZE: Final = 100),mypy 会阻止对它的直接赋值;
  • 但若通过实例访问(obj.MAX_SIZE = 200),mypy 通常不会报错(除非开启严格模式),且运行时生效;
  • 它不阻止对可变对象内容的修改(如 data: Final[list] = [1, 2]data.append(3) 完全合法)。

真正不可变需靠其他机制

若需要运行时不可变,应结合其他手段:

立即学习Python免费学习笔记(深入)”;

  • 使用 tuplefrozenset 等内置不可变类型;
  • @dataclass(frozen=True) 冻结数据类,尝试修改属性会抛出 FrozenInstanceError
  • 自定义 __setattr__ 或用 __slots__ 配合逻辑控制;
  • 配合 mypy + CI 检查,把 Final 当作协作规范来用。
text=ZqhQzanResources