模块顶层定义最安全,避免用class封装常量;应显式导入而非from … import *;环境相关常量需通过os.getenv读取;类型提示须用final或literal增强检查。

常量该不该放进 class 里? python 没有语言级常量,所谓“常量”只是约定(全大写 + 不改)。但放哪儿最不踩坑?直接塞模块顶层最安全。用 class 封装看似整洁,实则容易误用:类属性会被实例意外修改(尤其用了可变对象),继承时还可能被子类覆盖。更麻烦的是 ide 和类型检查器(如 mypy)对 class 内常量的推导支持弱,typing.Literal 或 Final 很难生效。
- 模块级定义:直接在
constants.py 里写 MAX_RETRY = 3、API_TIMEOUT = 30.0
- 避免
class Constants: 这种包装,除非你明确需要命名空间隔离(比如多个业务域常量易重名)
- 如果真要用类,必须加
<strong>slots</strong> = () 并配合 typing.Final(仅 Python 3.8+),否则形同虚设
from constants import * 为什么危险? 这种导入方式会让常量“隐身”——你没法一眼看出某个变量是哪来的,重构时也难以定位引用。更重要的是,它会污染当前命名空间,和本地变量、函数名冲突后,错误往往延迟到运行时才暴露(比如覆盖了内置 id 或 list)。
- 始终用显式导入:
from constants import MAX_RETRY, API_TIMEOUT
- 或者只导入模块本身:
import constants,然后用 constants.MAX_RETRY
- 如果常量太多,考虑按用途拆分文件,比如
http_constants.py、db_constants.py
环境相关常量怎么处理? 硬编码 DEV_URL = "https://www.php.cn/link/fcbb3a1c04ec11f1506563c26ca63774" 和 PROD_URL = "https://api.example.com" 是反模式。运行时该用哪个,取决于部署环境,不是开发时能定死的。
- 把环境变量作为唯一可信源:
os.getenv("API_BASE_URL", "<a href="https://www.php.cn/link/fcbb3a1c04ec11f1506563c26ca63774">https://www.php.cn/link/fcbb3a1c04ec11f1506563c26ca63774</a>")
- 在
constants.py 里封装读取逻辑,而不是存字符串值:
import os API_BASE_URL = os.getenv("API_BASE_URL", "https://www.php.cn/link/fcbb3a1c04ec11f1506563c26ca63774") JWT_ALGORITHM = os.getenv("JWT_ALGORITHM", "HS256")
- 切忌在常量模块里做复杂逻辑(如条件判断选 URL),那已经不属于“常量”范畴了
类型提示怎么加才有效? 光写 DB_PORT = 5432,mypy 默认当 int 看,但实际它永远是这个值。用 Literal 或 Final 才能让类型系统真正帮你卡住错误。
constants.py 里写 MAX_RETRY = 3、API_TIMEOUT = 30.0 class Constants: 这种包装,除非你明确需要命名空间隔离(比如多个业务域常量易重名)<strong>slots</strong> = () 并配合 typing.Final(仅 Python 3.8+),否则形同虚设from constants import * 为什么危险? 这种导入方式会让常量“隐身”——你没法一眼看出某个变量是哪来的,重构时也难以定位引用。更重要的是,它会污染当前命名空间,和本地变量、函数名冲突后,错误往往延迟到运行时才暴露(比如覆盖了内置 id 或 list)。
- 始终用显式导入:
from constants import MAX_RETRY, API_TIMEOUT - 或者只导入模块本身:
import constants,然后用constants.MAX_RETRY - 如果常量太多,考虑按用途拆分文件,比如
http_constants.py、db_constants.py
环境相关常量怎么处理? 硬编码 DEV_URL = "https://www.php.cn/link/fcbb3a1c04ec11f1506563c26ca63774" 和 PROD_URL = "https://api.example.com" 是反模式。运行时该用哪个,取决于部署环境,不是开发时能定死的。
- 把环境变量作为唯一可信源:
os.getenv("API_BASE_URL", "<a href="https://www.php.cn/link/fcbb3a1c04ec11f1506563c26ca63774">https://www.php.cn/link/fcbb3a1c04ec11f1506563c26ca63774</a>")
- 在
constants.py 里封装读取逻辑,而不是存字符串值:
import os API_BASE_URL = os.getenv("API_BASE_URL", "https://www.php.cn/link/fcbb3a1c04ec11f1506563c26ca63774") JWT_ALGORITHM = os.getenv("JWT_ALGORITHM", "HS256")
- 切忌在常量模块里做复杂逻辑(如条件判断选 URL),那已经不属于“常量”范畴了
类型提示怎么加才有效? 光写 DB_PORT = 5432,mypy 默认当 int 看,但实际它永远是这个值。用 Literal 或 Final 才能让类型系统真正帮你卡住错误。
os.getenv("API_BASE_URL", "<a href="https://www.php.cn/link/fcbb3a1c04ec11f1506563c26ca63774">https://www.php.cn/link/fcbb3a1c04ec11f1506563c26ca63774</a>") constants.py 里封装读取逻辑,而不是存字符串值:
import os API_BASE_URL = os.getenv("API_BASE_URL", "https://www.php.cn/link/fcbb3a1c04ec11f1506563c26ca63774") JWT_ALGORITHM = os.getenv("JWT_ALGORITHM", "HS256")
DB_PORT = 5432,mypy 默认当 int 看,但实际它永远是这个值。用 Literal 或 Final 才能让类型系统真正帮你卡住错误。
常量看着简单,但一旦混进环境逻辑、类型模糊、导入随意,后面查问题的人会花三倍时间还原上下文。最稳妥的做法,其实是少而明确:一个文件、全大写、不带逻辑、类型标清、环境靠外置。