如何修改从property装饰器获取的对象?Python场景解析
问题原因分析
你遇到的问题核心在于:每次访问a.foo时,getter方法都会调用json.loads(self._foo)生成一个全新的字典对象。你修改的只是这个临时字典,和类内部存储的_foo JSON字符串没有任何关联——下次再访问a.foo时,又会从原始的_foo重新解析出字典,之前的修改自然就丢失了。
解决方案
下面提供几种不同场景下的解决办法,你可以根据自己的需求选择:
方案1:修改后重新赋值(简单直接)
这是最容易实现的方式:先把foo的字典取出来,修改后再重新赋值给foo,触发setter方法更新_foo:
a = A() # 先获取字典副本 temp_dict = a.foo # 修改内容 temp_dict['name'] = 'new_name' # 重新赋值,触发setter同步到_foo a.foo = temp_dict print(a.foo['name']) # 输出: new_name print(a._foo) # 输出: {"name": "new_name"}
方案2:使用代理字典(支持直接修改)
如果你希望像操作普通字典一样直接修改a.foo的内容,并且自动同步到_foo,可以写一个代理字典类,拦截字典的修改操作,实时更新_foo:
import json class ProxyDict(dict): def __init__(self, parent_instance): # 从父类的_foo加载初始数据 super().__init__(json.loads(parent_instance._foo)) self.parent = parent_instance def __setitem__(self, key, value): # 先执行普通字典的赋值操作 super().__setitem__(key, value) # 同步更新父类的_foo为JSON字符串 self.parent._foo = json.dumps(self) class A(object): _foo = '{"name":"name"}' @property def foo(self): # 返回代理字典实例 return ProxyDict(self) @foo.setter def foo(self, value): self._foo = json.dumps(value)
现在你就可以直接修改a.foo的内容了,修改会自动同步到_foo:
a = A() a.foo['name'] = 'new_name' print(a.foo['name']) # 输出: new_name print(a._foo) # 输出: {"name": "new_name"}
方案3:直接存储字典(如果允许的话)
如果你的业务场景不需要把_foo保持为JSON字符串,可以直接把_foo存储为字典类型,这样getter返回的就是同一个字典对象,修改自然会同步:
import json class A(object): # 直接存字典,而不是JSON字符串 _foo = {"name":"name"} @property def foo(self): return self._foo @foo.setter def foo(self, value): # 如果需要兼容传入JSON字符串的情况,可以加判断 if isinstance(value, str): self._foo = json.loads(value) else: self._foo = value
使用方式和你之前预期的完全一致:
a = A() a.foo['name'] = 'new_name' print(a.foo['name']) # 输出: new_name
内容的提问来源于stack exchange,提问作者pktangyue
相关产品推荐
相关产品推荐

