python - How to define a super powerful class-style dict object? -
assume object meeting need called classdic
, functions of instance of class classdic
are:
query, update, add, , delete data can realized in class style way , dict style way (called "two ways").
when attribute or key not existing, instance of classdic can automatically build , make equal default value on both instance , dict, can query both ways (note: not add, query).
so, how can implement class?
the example below shows how instance of class work:
dic={'one':1, 'two':{'four':4,'five':{'six':6,'seven':7}}, 'three':3} cdic=classdic(dic,default=100) -------------------query in 2 ways------------------------------------------- >>> cdic.one 1 >>> cdic.two {'four':4,'five':{'six':6,'seven':7}} >>> cdic.two.five.six 6 >>> cdic['two']['five']['six'] 6 -------------------update in 2 ways------------------------------------------- >>> cdic['two']['five']['six']=7 >>> cdic.two.five.six 7 >>> cdic.two.five.six=8 >>> cdic['two']['five']['six'] 8 -------------------add in 2 ways------------------------------------------- >>> cdic['two']['five']['eight']=8 >>> cdic.two.five.eight 8 >>> cdic.two.five.nine=9 >>> cdic['two']['five']['nine'] 9 -------------------query default in 2 ways------------------------------------------- >>> print cdic['ten'] 100 >>> cdic.ten 100 >>> print cdic.eleven 100 >>> cdic['eleven'] 100 -------------------the final state of cdic------------------------------------------- >>> cdic {'eleven': 100, 'three': 3, 'two': {'four': 4, 'five': {'nine': 9, 'seven': 7, 'six': 8, 'eight': 8}}, 'ten': 100, 'one': 1}
subclass collections.defaultdict()
:
from collections import defaultdict, mapping class default_attribute_dict(defaultdict): def __init__(self, *args, **kwargs): super(default_attribute_dict, self).__init__(*args, **kwargs) self.__dict__ = self def __getattr__(self, name): # trigger default return self[name] @classmethod def from_dictionaries(cls, d, default=lambda: none): cdic = cls(default) key, value in d.iteritems(): if isinstance(value, mapping): value = cls.from_dictionaries(value, default=default) cdic[key] = value return cdic
this not automatically create nested instances of itself; you'll need loop on input dictionary , create nested objects yourself.
but offer attribute access , default values:
>>> cdic = default_attribute_dict(lambda: 100) >>> cdic.hundred 100 >>> cdic['ten'] = 10 >>> cdic.ten 10 >>> cdic['ten'] 10
to build tree existing dictionary, use from_dictionaries()
class method:
>>> cdic = default_attribute_dict.from_dictionaries(dic, default=lambda: 100) >>> cdic defaultdict(<function <lambda> @ 0x109998848>, {'one': 1, 'three': 3, 'two': defaultdict(<function <lambda> @ 0x109998848>, {'four': 4, 'five': defaultdict(<function <lambda> @ 0x109998848>, {'seven': 7, 'six': 6})})}) >>> cdic.two.four 4
note keys on dictionary can mask methods; keep in mind when inserting keys match dictionary methods:
>>> cdic = default_attribute_dict.from_dictionaries(dic, default=lambda: 100) >>> cdic.keys <built-in method keys of default_attribute_dict object @ 0x7fdd0bcc9ac0> >>> cdic['keys'] 100 >>> cdic.keys 100 >>> cdic.keys() traceback (most recent call last): file "<stdin>", line 1, in <module> typeerror: 'int' object not callable
Comments
Post a Comment