递归地将dict中的所有dict转换为自定义dict类



这个类在键不存在时返回None(而不是崩溃整个应用程序),并允许访问像属性这样的键:

class Dict(dict):  # a dictionary that returns @None when a key doesn't exist (as opposed to crashing the entire application...) and allows accessing keys like attributes
def __init__(   self, *args,**kwargs):
super(Dict,self).__init__(*args,**kwargs)
self.__dict__ = self  # this allows accessing keys like attributes
def __getitem__(self, key,default=None):
return dict.get(self, key,default)  # return None if the key exists not
def __getattribute__(self, attr):  # return None if the attribute exists not
try:                    return object.__getattribute__(self,attr)
except AttributeError:  return None

你可以这样使用:

x = Dict({'a':0, 'b':1})
print(x['a'], x.a)
print(x['c'], x.c)

问题是这不能递归地应用:

x = Dict({'a':{'aa':0x00}, 'b':1})
print(x['a'], x.a)
print(x.a['aa'])
print(x.a.aa)  # AttributeError: 'dict' object has no attribute 'aa'

如何解决这个问题?

让我们考虑一下您的需求。首先,你想要一些东西,为丢失的键返回None,即defaultdict类行为。然而,在实际代码中,您会发现即使是defaultdict也常常太神奇了。通常您希望知道键丢失的时间,而不是静默地返回None,而不是"崩溃整个应用程序"。你可以捕获异常:

try:
di[key]
except KeyError:
# handle missing key

第二,需要属性访问。这是可以理解的,因为写di.a比写di['a']要好得多(特别是在我的芬兰语键盘和许多其他键盘上,在修改键后面有方括号!)然而,将属性访问和项访问(类似字典的行为)混合到同一个对象中是有问题的。例如,考虑您的Dict。如果有人做了呢

di = Dict()
di['keys'] = ['C#', 'D']
di.keys()  # TypeError: 'list' object is not callable

现在,您的对象不再作为字典正常工作。同样的问题也适用于其他的字典方法。我猜你可以编写__setitem__()__setattribute__()保护来防止覆盖字典方法,但它开始变得复杂。

在我看来,你应该决定你是想要项目访问还是属性访问,而不是试图实现两者。如果需要属性,数据类是很好的选择(您可以实现__getattr__()以返回缺失属性的None)。如果你想要访问项目,只需使用defaultdict

相关内容

  • 没有找到相关文章