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即可
posted @ 2023-07-22 13:07  顺其自然,道法自然  阅读(120)  评论(0编辑  收藏  举报