模块顶层定义最安全,避免用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 才能让类型系统真正帮你卡住错误。
- 基础值用
Final:MAX_RETRY: Final[int] = 3
- 枚举类常量优先用
Enum,别用字符串元组;如果非用字符串,上 Literal:LOG_LEVEL: Final[Literal["DEBUG", "INFO", "ERROR"]] = "INFO"
- 注意
Final 不阻止运行时修改(Python 无强制),但它让 mypy 报错:MAX_RETRY = 5 会触发 error: Cannot assign to final attribute
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 才能让类型系统真正帮你卡住错误。
- 基础值用
Final:MAX_RETRY: Final[int] = 3
- 枚举类常量优先用
Enum,别用字符串元组;如果非用字符串,上 Literal:LOG_LEVEL: Final[Literal["DEBUG", "INFO", "ERROR"]] = "INFO"
- 注意
Final 不阻止运行时修改(Python 无强制),但它让 mypy 报错:MAX_RETRY = 5 会触发 error: Cannot assign to final attribute
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 才能让类型系统真正帮你卡住错误。
- 基础值用
Final:MAX_RETRY: Final[int] = 3 - 枚举类常量优先用
Enum,别用字符串元组;如果非用字符串,上Literal:LOG_LEVEL: Final[Literal["DEBUG", "INFO", "ERROR"]] = "INFO" - 注意
Final不阻止运行时修改(Python 无强制),但它让 mypy 报错:MAX_RETRY = 5会触发error: Cannot assign to final attribute
常量看着简单,但一旦混进环境逻辑、类型模糊、导入随意,后面查问题的人会花三倍时间还原上下文。最稳妥的做法,其实是少而明确:一个文件、全大写、不带逻辑、类型标清、环境靠外置。
专为中小型企业定制的网络办公软件,富有竞争力的十大特性: 1、独创 web服务器、数据库和应用程序全部自动傻瓜安装,建立企业信息中枢 只需3分钟。 2、客户机无需安装专用软件,使用浏览器即可实现全球办公。 3、集成Internet邮件管理组件,提供web方式的远程邮件服务。 4、集成语音会议组件,节省长途话费开支。 5、集成手机短信组件,重要信息可直接发送到员工手机。 6、集成网络硬








