Python 2.7中自定义类为何默认出现记忆化(缓存)行为?
问题根源:可变对象的引用传递,而非Python自动缓存实例
首先明确:Python 不会自动缓存类的实例,你遇到的现象完全是因为字典是可变对象,且两个实例共享了同一个字典引用。
具体分析两种场景:
第一种场景(出现"缓存"错觉)
你创建的test_dict是一个字典对象,两次实例化MyClient时都传入了这个同一个对象:test_dict = {"foo": "bar"} x = MyClient(test_dict).run() y = MyClient(test_dict).run()MyClient的__init__里只是把self.value指向传入的字典,并没有创建新字典。所以两个实例的self.value其实是同一个字典对象的引用。当run方法修改self.value时,本质是修改了这个共享的字典,自然另一个实例的self.value也会看到变化——这不是实例被缓存,是字典本身被共享了。第二种场景(无"缓存"现象)
test_dict = {"foo": "bar"} x = MyClient(test_dict) y = MyClient({"foo": "bar"})这里
y的实例化传入的是新创建的字典对象({"foo": "bar"}会生成一个全新的字典,内存地址和test_dict不同),所以x.value和y.value指向两个独立的字典,修改其中一个不会影响另一个。
额外的代码错误
你的run方法定义有问题:
def run(): # do some stuff and update self.value
在Python 2.7中,实例方法必须把self作为第一个参数,否则调用时会抛出TypeError: run() takes no arguments (1 given)。你实际运行的代码应该是修正后的:
def run(self): # do some stuff and update self.value
验证方法
可以打印对象的内存地址确认:
test_dict = {"foo": "bar"} x_inst = MyClient(test_dict) y_inst = MyClient(test_dict) print(id(x_inst.value)) # 和下面的输出相同 print(id(y_inst.value)) z_inst = MyClient({"foo": "bar"}) print(id(z_inst.value)) # 和上面的输出不同
解决办法
如果希望每个MyClient实例拥有独立的字典副本,在__init__里复制传入的字典:
class MyClient(object): def __init__(self, my_dict): self.value = dict(my_dict) # 创建字典副本 # 或者 self.value = my_dict.copy() def run(self): # 修改self.value只会影响当前实例的副本 self.value["new_key"] = "new_value"
内容的提问来源于stack exchange,提问作者Klutch27
相关产品推荐
相关产品推荐

