https://github.com/makinacorpus/easydict
可惜有个问题 如果 key 不存在会爆出错误 我觉得返回 None 比较合理
#_*_ coding: utf-8 _*_
# https://github.com/makinacorpus/easydict
class EasyDict(dict):
"""
Get attributes
>>> d = EasyDict({'foo':3})
>>> d['foo']
3
>>> d.foo
3
>>> d.bar
Traceback (most recent call last):
...
AttributeError: 'EasyDict' object has no attribute 'bar'
Works recursively
>>> d = EasyDict({'foo':3, 'bar':{'x':1, 'y':2}})
>>> isinstance(d.bar, dict)
True
>>> d.bar.x
1
Bullet-proof
>>> EasyDict({})
{}
>>> EasyDict(d={})
{}
>>> EasyDict(None)
{}
>>> d = {'a': 1}
>>> EasyDict(**d)
{'a': 1}
Set attributes
>>> d = EasyDict()
>>> d.foo = 3
>>> d.foo
3
>>> d.bar = {'prop': 'value'}
>>> d.bar.prop
'value'
>>> d
{'foo': 3, 'bar': {'prop': 'value'}}
>>> d.bar.prop = 'newer'
>>> d.bar.prop
'newer'
Values extraction
>>> d = EasyDict({'foo':0, 'bar':[{'x':1, 'y':2}, {'x':3, 'y':4}]})
>>> isinstance(d.bar, list)
True
>>> from operator import attrgetter
>>> map(attrgetter('x'), d.bar)
[1, 3]
>>> map(attrgetter('y'), d.bar)
[2, 4]
>>> d = EasyDict()
>>> d.keys()
[]
>>> d = EasyDict(foo=3, bar=dict(x=1, y=2))
>>> d.foo
3
>>> d.bar.x
1
Still like a dict though
>>> o = EasyDict({'clean':True})
>>> o.items()
[('clean', True)]
And like a class
>>> class Flower(EasyDict):
... power = 1
...
>>> f = Flower()
>>> f.power
1
>>> f = Flower({'height': 12})
>>> f.height
12
>>> f['power']
1
>>> sorted(f.keys())
['height', 'power']
"""
def __init__(self, d=None, **kwargs):
if d is None:
d = {}
if kwargs:
d.update(**kwargs)
for k, v in d.items():
setattr(self, k, v)
# Class attributes
for k in self.__class__.__dict__.keys():
if not (k.startswith('__') and k.endswith('__')):
setattr(self, k, getattr(self, k))
def __setattr__(self, name, value):
if isinstance(value, (list, tuple)):
def get_EasyDict_list(value):
return [EasyDict(x) if isinstance(x, dict) else x if not isinstance(x, (list, tuple)) else get_EasyDict_list(x) for x in value]
value = get_EasyDict_list(value)
else:
value = EasyDict(value) if isinstance(value, dict) else value
super(EasyDict, self).__setattr__(name, value)
self[name] = value
def __getattr__(self, name):
"""
如果 key 不存在返回 None
"""
try:
return super(EasyDict, self).__getattr__(name)
except AttributeError:
try:
return self[name]
except KeyError:
key = name or ""
if key.startswith('__') and key.endswith('__'):
raise AttributeError
return None
if __name__ == "__main__":
import doctest
doctest.testmod()
import json
d = EasyDict({'a': 1, 'b': [1,2], 'c': {'x': 1, 'y': 2},'d':[[{'x':3, 'y':4}]]})
print d.a
print d.b
print d.c
print d.c.x, d.c.y
print d.d
print d.e
d.e = 100
print d.e
d.c.z = 4
d.b.append(10)
print d.d[0][0].x
print d.d[0][0].y
d.f = [1,2,3,4,5]
print d.f
print d['f']
print json.dumps(d)
print(hasattr(d, 'a'))
print(hasattr(d, 'b'))
print(hasattr(d, 'adfasfc'))
print(hasattr(d, 'd'))
print(hasattr(d[0][0], 'x'))
print(hasattr(d[0][0], 'y'))
print(hasattr(d[0][0], 'z'))
x = EasyDict()
x['abcd'] = 10
print(x['abcd'])
print(x.abcd)