我目前正在尝试为python字典类
dict
实现一个子类(称为'Pointer_dict')。此类的目的是在创建字典副本并在不更改原始字典的情况下更改其值时节省内存。这就是为什么,我不使用deepcopy()
.
Pointer_dict 类应该采用现有字典并在调用时(例如
tmp['foo']
)返回原始值(如果存在)(否则 KeyError),但如果该值之前被覆盖,则返回其自己的值。
演示:
original = { 'foo': 1, 'bar': 2 }
pointer_dict = Pointer_dict(origin=original)
print(pointer_dict['foo']) # 1
pointer_dict['foo'] = 10
print(pointer_dict['foo']) # 10
print(original['foo']) # 1
所以它指向自己的值,当它们被设置时,但指向原始字典,当它没有被设置时。 嵌套字典出现此问题。 假设我们有:
original = { 'foo': 1, 'bar': { 'foobar': 2, 'barfoo': 3 } }
pointer_dict = Pointer_dict(origin=original)
print(pointer_dict['foo']) # 1
pointer_dict['bar']['foobar'] = 10
print(pointer_dict['bar']['foobar']) # 10
print(original['bar']['foobar']) # 2
因为我们只设置了
['bar']['foobar']
pointer_dict 只包含{ 'bar': { 'foobar': 10} }
,因为它不应该复制原始值(由于内存节省),而只是指向它们。
所以我现在面临的问题是,如果我想打印 pointer_dict
本身或 pointer_dict['bar']
我希望输出看起来像:
{ 'foo': 1, 'bar': { 'foobar': 10, 'barfoo': 3 } } # print(pointer_dict)
{ 'foobar': 10, 'barfoo': 3 } # print(pointer_dict['bar'])
所以我的问题是,如何实现 __getitem__ 和 __repr__ 方法,返回值是它自己的值和原始值的混合?
如果我使用普通字典作为返回值,那么嵌套列表将不起作用,因为在一次 __getitem__ 调用之后,返回值是一个字典,然后我自己的 __getitem__ 方法将不会被调用用于深度嵌套列表,所以它会返回错误的值。
到目前为止我的做法是这样的(我还没有尝试实施
__repr__
,因为我以前的方法不起作用):
class Pointer_Dict(dict):
def __init__(self, mapping={}, /, **kwargs):
self.origin = kwargs['kwargs']
super().__init__(mapping)
def __setitem__(self, key, value) -> None:
if isinstance(value, dict):
value = Pointer_Dict(value, kwargs=self.origin[key])
super().__setitem__(key, value)
def __getitem__(self, key):
try:
val_dict = super().__getitem__(key)
try:
val_orig = self.origin[key]
if isinstance(val_orig, dict):
return Pointer_Dict(mapping=val_dict, kwargs=val_orig)
except KeyError:
return val_dict
except KeyError:
try:
val_orig = self.origin[key]
if isinstance(val_orig, dict):
return Pointer_Dict(kwargs=val_orig)
return val_orig
except KeyError:
raise KeyError(key)
return val_dict
我的想法是采用递归方法,只要值仍然是字典/字典的子类,它就会调用
__getitem__
,并且仅在遇到不是字典的内容时才返回值。
......但这没有用,我没有得到正确的价值观,我对如何解决问题有点迷茫......
所以我愿意接受任何关于如何解决这个问题的新建议! 提前谢谢你!