【发布时间】:2020-09-01 13:59:23
【问题描述】:
我对代码中的错误感到困惑:
给定以下类,方法为distribute_tags
class ConsulData:
def __init__(self, logger, marshalled_data, prom_numbering, prom_count):
self.logger = logger
self.current = marshalled_data
self.to_update= {}
self.payloads = []
self.prom_count = prom_count
self.prom_numbering = prom_numbering
def distribute_tags(self):
cpt = 0
cp_current = copy.deepcopy(self.current)
for keys, values in cp_current.items():
num = (cpt % self.prom_count) + self.prom_numbering
prometheus_tag = "prometheus-{}".format(num)
if not prometheus_tag in values['Tags']:
self.to_update[keys] = values
data = []
[data.append(v) for v in values['Tags'] if not v.startswith("prometheus")]
data.append(prometheus_tag)
self.to_update[keys]['Tags'] = data
cpt += 1
{...}
没有deepcopy,循环执行后,print(self.current == self.to_update)返回True。
而print(id(self.current) == id(self.to_update)) 返回 False。
deepcopy 的使用修复了我意想不到的错误,因为 distribute_tags 内部所做的事情或多或少与做的事情相同:
In [2]: d1 = {'key1':'value1', 'key2':'value2'}
In [3]: d2 = {}
In [4]: for k, v in d1.items():
...: d2[k] = v
In [6]: d2['key1'] = 'lol'
In [8]: d1
Out[8]: {'key1': 'value1', 'key2': 'value2'}
In [9]: d2
Out[9]: {'key1': 'lol', 'key2': 'value2'}
其中 d1 数据不受 d2 修改的影响,因为它们是对不同对象的 2 个不同引用。
传递给 init 函数的 marshalled_data 如下所示:
payload = {
'service1': {
'ID': 'service1',
'Service': 'service1',
'Tags': ['sre-metrics', 'prometheus-2'],
'Meta': {
'env': 'dev',
'namespace': 'test',
'path': '/path1',
'svc': 'svc1',
'team': 'testing'},
'Port': 80,
'Address': 'test1.testing.org',
'Weights': {'Passing': 1, 'Warning': 1},
'EnableTagOverride': False
},
...
【问题讨论】:
-
self.to_update[keys] = values不会复制values。因此,当您使用self.to_update[keys]['Tags'] = data时,如果您不使用deepcopy(),那么您也在修改原始字典 -
谢谢@Barmar 我把它当作答案
标签: python class dictionary reference