Python2.7转Python3:全局不可修改常量实现方案替换咨询
Python2到Python3全局不可修改常量方案迁移
你原来基于Python2的常量方案在Python3失效,主要是因为两个语法变更:字典has_key()方法被移除,以及异常抛出语法调整。下面提供修复原有方案和更优的替代方案:
一、修复原有方案适配Python3
修改const.py中的两处Python2特有语法:
# const.py class _const: class ConstError(TypeError): pass def __setattr__(self, name, value): # 替换has_key为in操作符 if name in self.__dict__: # Python3的异常抛出语法 raise self.ConstError(f"Can't rebind const({name}) look at the log, it should only be set in constants.py") self.__dict__[name] = value import sys sys.modules[__name__] = _const()
test.py的print语句已改为Python3格式,修改后原有代码逻辑可正常运行,重新赋值常量会触发ConstError。
二、更Pythonic的最优替代方案
1. 内置enum.Enum(推荐)
Python3.4+内置的enum模块是定义常量的标准方式,类型安全且语义清晰:
# constants.py from enum import Enum class GlobalConst(Enum): PASS = 0 FAIL = -1 INT_VAL = 1234 STR_VAL = 'This is a string'
使用示例:
# test.py from constants import GlobalConst print('INT_VAL is ', GlobalConst.INT_VAL.value) print('STR_VAL is ', GlobalConst.STR_VAL.value)
如果需要直接使用常量值而非枚举实例,可直接定义模块级变量,并通过模块钩子防止修改:
# constants.py PASS = 0 FAIL = -1 INT_VAL = 1234 STR_VAL = 'This is a string' class ConstError(TypeError): pass def __setattr__(name, value): raise ConstError(f"Cannot modify constant {name}") __all__ = ['PASS', 'FAIL', 'INT_VAL', 'STR_VAL']
2. 冻结数据类(Python3.7+)
用dataclasses的frozen=True创建不可变数据类,适合结构化常量集合:
# constants.py from dataclasses import dataclass @dataclass(frozen=True) class GlobalConst: PASS: int = 0 FAIL: int = -1 INT_VAL: int = 1234 STR_VAL: str = 'This is a string' gc = GlobalConst()
使用示例:
# test.py from constants import gc print('INT_VAL is ', gc.INT_VAL) print('STR_VAL is ', gc.STR_VAL) # 尝试修改会抛出FrozenInstanceError
方案选择建议
- 修复原有方案:适合需要完全兼容旧代码结构的场景,但语法偏老旧
enum.Enum:官方推荐,类型安全,支持枚举特性,是大多数场景的最优选择- 冻结数据类:适合需要组织成结构化的常量集合,支持类型注解
内容的提问来源于stack exchange,提问作者Mick Sulley
相关产品推荐
相关产品推荐

