Python无语言级常量,const/final等关键字不被支持;所谓常量仅靠全大写命名约定,运行时可随意重赋值;typing.Final仅在静态类型检查时提示错误,运行时无效;可通过__slots__+@property实现运行时只读实例属性;enum适合定义有限互斥状态,不适用于标量常量;生产环境应优先用测试保障常量不变性。

Python 没有语言级常量,const 不存在
Python 解释器不支持 const、final 或类似关键字声明不可变绑定。所谓“常量”只是约定俗成的命名惯例(如全大写 MAX_RETRY),解释器完全允许你重新赋值:MAX_RETRY = 5 之后再写 MAX_RETRY = 10 不会报错,也不会警告。
这种设计源于 Python 的动态性哲学——名字只是对象的标签,绑定可随时更改。想靠语法强制阻止修改,做不到。
用 typing.Final 做类型检查层面的约束
typing.Final 是唯一接近“常量语义”的标准方案,但它只在静态类型检查时起作用(如 mypy),运行时不生效:
from typing import FinalPI: Final[float] = 3.14159 PI = 3.14 # mypy 报错:Cannot assign to final attribute "PI"
- 必须配合类型检查工具使用,
python script.py直接运行完全无视Final - 仅对模块级变量有效;类属性上用
Final需搭配@final类装饰器(Python 3.12+)才更严谨 - 不能防止对可变对象内容的修改,例如
LIST: Final = [1, 2]后仍可执行LIST.append(3)
用 __slots__ + 只读属性模拟不可变实例常量
若需在类中封装一组运行时不可变的值(比如配置项),可结合 __slots__ 和 @property 实现真正只读的实例属性:
立即学习“Python免费学习笔记(深入)”;
class Config:
__slots__ = ("_host", "_port")
def __init__(self, host: str, port: int):
self._host = host
self._port = port
@property
def host(self) -> str:
return self._host
@property
def port(self) -> int:
return self._portcfg = Config("localhost", 8000)
动态WEB网站中的PHP和MySQL:直观的QuickPro指南第2版
动态WEB网站中的PHP和MySQL详细反映实际程序的需求,仔细地探讨外部数据的验证(例如信用卡卡号的格式)、用户登录以及如何使用模板建立网页的标准外观。动态WEB网站中的PHP和MySQL的内容不仅仅是这些。书中还提到如何串联JavaScript与PHP让用户操作时更快、更方便。还有正确处理用户输入错误的方法,让网站看起来更专业。另外还引入大量来自PEAR外挂函数库的强大功能,对常用的、强大的包
下载
cfg.host = "new" # AttributeError: can't set attribute
-
__slots__禁止动态添加属性,减少内存占用并提前暴露非法赋值 -
@property去掉setter即实现运行时只读,比Final更实在 - 注意:仍无法阻止通过
object.__setattr__(cfg, "_host", "hacked")绕过,但已覆盖绝大多数误用场景
第三方方案如 constantly 或 enum.Enum 的适用边界
enum.Enum 适合定义一组互斥、有限、带名称的固定值(如状态码 Status.ACTIVE),但它不是通用常量容器——每个成员是独立对象,不能直接用于数学运算或字符串拼接,且不支持 float/int 字面子类化(除非用 IntEnum)。
constantly 这类库本质是封装了带 __set__ 魔法方法的描述符,能拦截赋值,但会引入额外依赖,且可能与某些框架(如 Pydantic v2 的模型字段)产生冲突。
- 优先用
enum表达“选择集”,不用来替代API_TIMEOUT = 30这类标量常量 - 生产环境慎用描述符型常量库,调试时容易卡在
__set__里,且 IDE 支持弱于Final - 真正的硬性约束只能靠测试覆盖:在 CI 中加断言验证关键常量未被意外重赋值
最易被忽略的一点:所谓“常量”的生命周期和作用域常常比想象中更短。模块级全大写变量在热重载、多线程导入、或被 importlib.reload() 干扰时,行为并不稳定。如果逻辑真依赖不可变性,别省那几行 @property。








