python设计一个跨模块全局变量
python中有时候需要用到全局变量, 并且这个全局变量需要跨文件, 跨模块共享.
为此, 我设计了一个全局对象, 它有以下特点:
- 如果引用不存在的属性, 不报错, 而是返回None
- 如果为不存在的属性赋值, 则会自动生成这个属性, 后续就可以正常引用这个属性, 就像对象本身具有此属性一样
- 整个对象可以序列化, 后续可以从文件中恢复
- 对于以
_
开头的变量不进行序列化 - 一个不足之处是对于用户自定义属性不支持代码自动补全, 可以创建一个继承自这个对象的类来支持自动补全
代码如下:
import jsonpickle
import os
import Common
class G:
'''存放全局变量的类'''
def __getattr__(self, name):
# __setstate__仍然保持不存在状态, 以免序列化出错
if name == "__setstate__": raise AttributeError(name)
return None # 访问不存在的属性时, 返回None
def __setattr__(self, name, value):
'''不管属性是否存在, 都设置属性的值'''
object.__setattr__(self, name, value)
def __getstate__(self):
'''对于jsonpickle模块, 决定序列化哪些属性, 以'_'开头的属性不序列化'''
state = self.__dict__.copy()
# 创建一个临时副本进行迭代和删除操作
temp_dict = state.copy()
for key in temp_dict.keys():
if key.startswith('_'): del state[key]
return state
def save(self,path:str='Data.json'):
'''把当前对象保存到文件'''
# 将类的实例保存为JSON格式
json_string = jsonpickle.encode(self, indent=4)
# 将JSON字符串中的Unicode编码字符转换为原始字符
decoded_string = json_string.encode().decode('unicode_escape')
decoded_string = decoded_string.replace('\\', '\\\\') # 防止\d+出错
Common.WriteAllText(path,decoded_string)
def Restore(path:str='Data.json')->'G':
'''恢复对象'''
if not os.path.exists(path): return None
json_string = Common.ReadAllText(path)
obj = jsonpickle.decode(json_string)
return obj
g = G() # 在别的文件中可以直接引用全局变量g即可