Python字典中datetime对象的异常行为原因咨询
为什么修改字典b的'end'时,字典a的'end'也同步变化?
这事儿其实和datetime没啥关系,核心是Python里可变对象的引用赋值逻辑在搞鬼,咱们拿你的代码和预期对比着说:
先看你预期正常的整数场景
你代码里的self.x = self.y,整数是Python里的不可变对象——意思是一旦创建就没法修改它的内部值,赋值操作其实是把self.y的数值(也就是2)复制了一份给self.x。所以后续你修改self.x的时候,只是给self.x重新绑定了一个新的整数对象,完全不会影响self.y,这和你预期的一致。
再看出问题的字典场景
而字典是可变对象,当你写b = a的时候,根本不是复制了一个新的字典给b,而是让变量b和a指向内存里同一个字典对象。打个比方:就像你给同一个房间装了两扇门,a是第一扇门的钥匙,b是第二扇门的钥匙——不管你用哪把钥匙进去修改房间里的东西,从另一扇门看进去,房间里的东西肯定是变的。
你每次执行b['end'] = b['end'] + datetime.timedelta(days=3),本质是在修改这个共享字典里的end值,a作为指向同一个字典的变量,自然会看到同样的变化。
怎么解决?让a和b变成独立的字典
如果你想让a和b是两个互不影响的字典,需要创建字典的副本,常用的方法有这几种:
- 浅拷贝(适合你的场景,因为字典里的
datetime是不可变对象):b = a.copy() # 或者用dict()构造器 b = dict(a) - 字典推导式:
b = {key: value for key, value in a.items()} - 如果字典里还有嵌套的可变对象(比如字典里套字典、列表),需要用深拷贝:
import copy b = copy.deepcopy(a)
把你的代码里b = a换成上面任意一种方式,再运行就会发现修改b['end']时,a['end']再也不会跟着变了。
你的原代码:
import datetime class TBD: def __init__(self): self.x = 1 self.y = 2 print(self.x, self.y) self.run_it() def run_it(self): self.x = self.y z = 0 a = {'start': datetime.datetime.now(), 'end': datetime.datetime.now() + datetime.timedelta(days=1)} b = a # 这里是引用赋值 while z < 3: self.x += 1 z += 1 b['end'] = b['end'] + datetime.timedelta(days=3) print(b['end'], a['end']) print('x=', self.x, 'y=', self.y) TBD()
修改后的代码(用copy()):
import datetime class TBD: def __init__(self): self.x = 1 self.y = 2 print(self.x, self.y) self.run_it() def run_it(self): self.x = self.y z = 0 a = {'start': datetime.datetime.now(), 'end': datetime.datetime.now() + datetime.timedelta(days=1)} b = a.copy() # 创建副本 while z < 3: self.x += 1 z += 1 b['end'] = b['end'] + datetime.timedelta(days=3) print(b['end'], a['end']) print('x=', self.x, 'y=', self.y) TBD()
修改后的运行结果会是a['end']一直保持初始的日期,而b['end']每次增加3天,完全符合你的预期。
内容的提问来源于stack exchange,提问作者guyd
相关产品推荐
相关产品推荐

