有时候,我们可以像使用对象一样使用字典(这样就不用总是写
在Python 3中,覆盖/包装Python字典有了新规则。在Python2中,仅需要包装
在Flask模板(HTML模板)中,这种情况非常有用。通过使用
在Python 3中包装一个
mydict['blah']
了,而是可以写成mydict.blah
)。在Python 3中,覆盖/包装Python字典有了新规则。在Python2中,仅需要包装
__getattr__
和__setattr__
方法即可。当你包装这些方法时,你可以添加一些特殊处理的能力,比如在添加某个属性时进行数据清洗/过滤等操作。在Flask模板(HTML模板)中,这种情况非常有用。通过使用
__getattr__
过滤器,您可以在离开dict
之前对数据进行格式化。这样,在模板中(Python表达式可能看起来有点复杂),你只需写mymodel.blah
,并知道从blah
出来的文本已经是你想要的方式。在Python 3中包装一个
dict
有点麻烦。我不确定现在该怎么做。以下是两个粗略的实现,效果不佳:# messed up Python3 wrapped dictionary (sets work, but gets do not)
class AttrDict(dict):
def __init__(self, *args, **kwargs):
super(AttrDict, self).__init__(*args, **kwargs)
self.__dict__ = self
self.clean_strings()
def clean_strings(self):
for key, value in self.items():
self[key] = string_empty_to_none(value)
def __getattr__(self, name):
#this never gets called in Python 3
return self[name]
这里还有一个:
# sets don't work - Always throws: TypeError: 'AttrDict' object does not support item assignment
class AttrDict():
def __init__(self, *args, **kwargs):
self.data = dict()
self.data.__init__(*args, **kwargs)
self.clean_strings()
def clean_strings(self):
for key, value in self.data.items():
self.data[key] = string_empty_to_none(value)
def __getattr__(self, attr):
if attr in self.data:
return self.data[attr]
else:
raise AttributeError("--%r object has no attribute %r" % (type(self).__name__, attr))
def __setattr__(self, name, value):
if name == 'data':
super(AttrDict, self).__setattr__(name, value)
else:
self.data[name] = value
这是我的小工具方法的样子:
def string_empty_to_none(s):
if type(s) == str:
return None if (s.strip() == '') else s
return s
我知道在Python3中,你应该使用__getattribute__
而不是__getattr__
。但是当我这样做时,总是陷入无限循环。
注意:我要求的最终语法应该像这样:
>>> x = AttrDict({'some': 'value'})
>>> x['blah'] = 'hello world'
>>> print(x.blah)
hello world
>>> print(x.some)
value