我正在创建一个小型缓存类,并且复制方法似乎有问题。在缓存类中,有一个名为copy witch的方法返回使用当前类数据初始化的缓存类的新实例。问题是,当我从源类中删除某些内容时,它也会从复制版本中删除它。我已经包含了一些工作代码来演示这一点。有人知道为什么吗?
cfg = {
'level_1': {
'level_2': {
'item1': 10,
'item2': 20,
}
}
}
more_cfg = {
'level_3': {
'level_4': {
'item3': 10,
'item4': 20,
}
}
}
class Cache:
def __init__(self, *args, **kwargs):
self.nodes = args[0] if args else kwargs
def get(self, uri=None):
if not uri:
return self.nodes
def walk(_uri, nodes):
parts = _uri.split('/', 1)
key = parts.pop(0)
if key in nodes:
node = nodes[key]
if not parts:
return node
else:
return walk(parts[0], node)
return walk(uri, self.nodes)
def set(self, uri, *args, **kwargs):
def walk(_uri, nodes):
parts = _uri.split('/', 1)
key = parts.pop(0)
if key in nodes and parts:
return walk(parts[0], nodes[key])
elif len(_uri.split('/')) == 1:
value = args[0] if args else kwargs
nodes[key] = value
return walk(uri, self.nodes)
def dump(self, indent=None):
""" Dumps the contents of the cache to the screen.
The output from dump goes stdout and is used to view the cache contents.
Default indentation is a dot for each level.
:param indent:
indent (str): String to be use for indenting levels.
:return:
Nothing.
"""
indent = indent if indent else '.'
print('-------------------------------------------------------------------------------------------------------')
if self.nodes:
def walk(_cfg, count):
count += 1
for key, value in _cfg.items():
if isinstance(value, dict):
print(indent * count, key)
walk(value, count)
else:
if isinstance(value, str):
value = f'"{value}"'
print(indent * count, key, value)
walk(self.nodes, 0)
else:
print(' (No Data)')
print('-------------------------------------------------------------------------------------------------------')
def copy(self):
return Cache(self.nodes.copy())
def remove(self, uri):
""" Remove entree from cache.
Removes an entree from the cache if it exists.
:param uri:
uri (str): URI that points to the entree to remove.
:return:
Nothing.
"""
uri = uri.lstrip('/')
if self.exists(uri):
node = self.get('/'.join(uri.split('/')[:-1]))
del node[uri.split('/')[-1]]
def exists(self, uri):
""" Test if URI exists in the cache.
:param uri:
:return:
"""
return True if self.get(uri) else False
def destroy(self):
""" Destroy cache.
Deletes all entries in the cache.
:return:
Nothing.
"""
del self.nodes
self.nodes = {}
c = Cache(cfg)
print(c.get('level_1/level_2/item2'))
c.set('level_1/level_2/more_cfg', more_cfg)
if c.exists('level_1/level_2/more_cfg'):
print(c.get('level_1/level_2/more_cfg'))
cache_copy = c.copy()
cache_copy.dump()
c.remove('level_1/level_2/item1')
c.remove('level_1/level_2/item2')
c.dump()
cache_copy.dump()
答案 0 :(得分:2)
尝试使用deepcopy代替副本
如果您阅读文档:
浅表副本会构造一个新的复合对象,然后(在可能的范围内)将引用插入到原始对象中。
深层副本会构造一个新的复合对象,然后递归地将原始对象中发现的对象的副本插入其中。
强调我的。
答案 1 :(得分:1)
这是因为.copy()方法复制了现有引用。如上所述,您应该改用deepcopy。