#!/user/bin/python | |
import json | |
class DocumentBase(object): | |
def traversal_for_init_dict(self, items): | |
for k in items: | |
if type(items[k]) == dict: | |
setattr(self, k, DocumentDict(**items[k])) | |
elif type(items[k]) == list: | |
setattr(self, k, self.traversal_for_init_list(items[k])) | |
else: | |
setattr(self, k, items[k]) | |
return self.__dict__ | |
def traversal_for_init_list(self, items): | |
rc = [] | |
for n in xrange(len(items)): | |
if type(items[n]) == list: | |
rc.append(self.traversal_for_init_list(items[n])) | |
elif type(items[n]) == dict: | |
rc.append(DocumentDict(**items[n])) | |
else: | |
rc.append(items[n]) | |
return rc | |
def traversal_to_dict(self, rc, items): | |
for k in items: | |
if type(items[k]) == DocumentDict: | |
rc[k] = items[k].to_dict() | |
elif type(items[k]) == list: | |
rc[k] = self.traversal_to_list(items[k]) | |
else: | |
rc[k] = items[k] | |
def traversal_to_list(self, items): | |
rc = [] | |
for k in xrange(len(items)): | |
if type(items[k]) == list: | |
rc.append(self.traversal_to_list(items[k])) | |
elif type(items[k]) == DocumentDict: | |
rc.append(items[k].to_dict()) | |
else: | |
rc.append(items[k]) | |
return rc | |
class DocumentDict(DocumentBase): | |
def __init__(self, **kwargs): | |
self.traversal_for_init_dict(kwargs) | |
def __setitem__(self, key, value): | |
setattr(self, key, value) | |
def __getitem__(self, key): | |
return getattr(self, key) | |
def to_dict(self): | |
rc = {} | |
self.traversal_to_dict(rc, self.__dict__) | |
return rc | |
class DocumentList(DocumentBase): | |
def __init__(self, items): | |
if type(items) != list: | |
raise Exception("not list: %s" % str(items)) | |
self.__list__ = self.traversal_for_init_list(items) | |
def __getitem__(self, index): | |
return self.__list__[index] | |
def to_dict(self): | |
return self.traversal_to_list(self.__list__) | |
if __name__ == '__main__': | |
print 'test...' | |
test_case = { | |
"a": 1, | |
"b": 12.0, | |
"c": 'cccc', | |
"d": { "d1": 3333, "d2": "xxx"}, | |
"e": [ | |
{"e1": 6666}, | |
{"e2": 8888, "e3": { "e31":-1, "e32":[ "ss1", "ss2"] } }, | |
{"e4": [100, 200, 300] } | |
], | |
"f": [ [0, 1, 3], ['a', 'b'], [ {"f1":1}, {"f2": 2} ]] | |
} | |
test_case_list = [ test_case, test_case, test_case] | |
print json.dumps(test_case) | |
print json.dumps(test_case_list) | |
print 100, '='*80 | |
dd = DocumentDict() | |
dd2 = DocumentDict() | |
dd2.aaa_x=1 | |
dd2.bbb_y=2 | |
dd.a = 1 | |
dd.b = '2' | |
dd.c = [] | |
dd.d = dd2 | |
dd.c.append(dd2) | |
dd.c.append(dd2) | |
dd.c.append(dd2) | |
#print dd.a, dd.b, dd.c, dd.d | |
print dd.to_dict() | |
print 111, '='*80 | |
dd3 = DocumentDict(**test_case) | |
print dd3.to_dict() | |
print 222, '='*80 | |
print dd3.a, dd3.b, dd3.d, dd3.e, dd3.d.d1, dd3.d.d2 | |
print dd3.e[0].e1 | |
print dd3.e[1].e2, dd3.e[1].e3.e31, dd3.e[1].e3.e32, dd3.e[1].e3.e32[0] | |
print dd3.e[2].e4, dd3.e[2].e4[0] | |
print dd3.f[0], dd3.f[2][0].f1, dd3.f[2][1].f2 | |
print 333, '='*80 | |
ddl = DocumentList(test_case_list) | |
print ddl.to_dict() | |
print ddl[0].e[0].e1, ddl[1].e[1].e2 | |
DocumentDict() | |
print 'done' | |
![]() |
1
openroc OP |
![]() |
2
binux 2014-05-28 15:11:14 +08:00
class Obict(dict):
....__getattr__ = dict.__getitem__ ....__setattr__ = dict.__setitem__ |
![]() |
5
binux 2014-05-28 15:18:36 +08:00 ![]() @openroc 嵌套就是 return 的时候 Obict 包一下就完了,list 同理
而且,建议扩展基础类型的时候从 dict, 或者 UserDict 继承,保证类型兼容性。不然你让 keys, items, values, for loop 怎么办? |
![]() |
7
clino 2014-05-28 15:54:22 +08:00
这个有类似的作用:
https://code.google.com/p/ulipad/source/browse/trunk/modules/dict4ini.py 不过是用在ini文件上 d = DictIni('t2.ini', format="%s:%s", hideData=True) d.a.a = 'mama' d.a.b = 'lubs me!' d.b.a = 'i' d.b.b = 'lub bosunmi!' d.c.a = 'dada' d.c.b = 'lubs me too!' d.save() |
![]() |
8
chuangbo 2014-05-29 13:16:43 +08:00
赞同 @binux,继承 dict 是必须的。
web.py 的 Storage 是一个比较完整的实现。 https://github.com/webpy/webpy/blob/master/web/utils.py#L52 |