zoukankan      html  css  js  c++  java
  • python自建 属性访问 (内部一致) 的 字典 data type

    python自建 属性访问 (内部一致) 的 字典 date type

    taxonomy['Animalia']['Chordata']['Mammalia']['Carnivora']['Felidae']['Felis']['cat']
    #>>>>
    taxonomy.Animalia.Chordata.Mammalia.Carnivora.Felidae.Felis.cat
    

    继承dict,重写__getattr____settattr__ 就行了:

    class adict(dict):
        def __getattr__(self, attr):
            return self[attr]
    
        def __setattr__(self, attr, val):
            self[attr] = val
            
    d = adict(a={'b':9})
    print d.a
    # {u'b': 9}
    d.k = {'p':5}
    

    但是,再往里层属性访问:print d.a.b ,raiseAttributeError: 'dict' object has no attribute 'b' ; d.k = {'p':5} 这样新进入的也不支持。

    它只是个壳子,里层其实没有变;不能一层层用下去,用的时候你得时刻考虑 class type

    或者不停地显示转换类型 d = adict(a=adict({'b':9})) 这也太不 pythonic.

    d = adict({'j': [0]}, a=9, b={'p': 5})
    d.b.p
    #Out[436]: 5
    

    so,要 能属性访问方法一致,那得需要 把所有 自身下层的 dict 转 成 adict。

    这样:

    还需要重写 __setitem__ update code:

    class adict(dict):
        '''dict support attr access'''
    
        def __init__(self, ele_=None, **kwargs):
            self.update(ele_, **kwargs)
    
        def __setitem__(self, item, value):
            # ! key method !;  'dict[k] = v' will use 'self.__setitem__(k,v)'
            # not to recur , use super
            if not isinstance(value, type(self)) and isinstance(value, dict):
                value = type(self).conv(value)
            super(adict, self).__setitem__(item, value)
    
        def update(self, ele=None, **kwargs):
            # rewrite
            if ele:
                if hasattr(ele, "keys"):
                    for k in ele:
                        self[k] = ele[k]
                else:
                    for (k, v) in ele:
                        self[k] = v
            for k in kwargs:
                self[k] = kwargs[k]
    
        def __getattr__(self, attr):
            return self[attr]
    
        def __setattr__(self, attr, val):
            self[attr] = val
    
        @classmethod
        def conv(cls, dic):
            if not isinstance(dic, dict):
                return dic
            new_dic = cls.__new__(cls)  # not trigger __init__
            for k, v in dic.iteritems():
                # __setitem__ use this, need super
                super(cls, new_dic).__setitem__(k, cls.conv(v))
            return new_dic
        
    if __name__ == '__main__':
        print('>> any dict in will be converted to adict<<
    ')
        d = adict({'j': [0]}, a=9, b={'p': 5})  # creat a adict
        print(d, '
    ', type(d), type(d.b))  # subdict is also adict
        d.z = {'g': 6}  # setitem
        print(type(d.z), 'd.z.g:', d.z.g)
    
        d.update({'kk': {'ko': 76}})  # update to adict
        print(type(d.kk), 'd.kk.ko:', d.kk.ko, )
    
        #----##->----------------------------------------
        #----same as dict, shadow copy first level self-type container
        print('-.'*30)
        a = {1: 9, 'a': {u'p': 9}, 'b': [u'as']}
        b = adict(a)
        print('b is adict(b):', b is adict(b))  # False, same as dict
        # a is dict(a)
        # Out[263]: False
        print('-'*30)
        dic = dict(a)
        print([a[k] is dic[k] for k in a.keys()])
        adic = adict(b)
        print([b[k] is adic[k] for k in b.keys()])    
    

    这样只要是adict type,标识符的key, 内部都能通过属性访问了。


    插句话:python 的 dict 为什么不支持 属性访问?

    字典的key支持int ,而,属性名必须是标识符;dict支持了int作为key,自然就不能再支持属性访问(如果key 为int,你还得转换为 [key] 访问,这么基础的操作都不具有一致性了)

    另外,属性名,不能作为key这样变量来随意改变;不够动态,而python可是动态语言。

    作为基础的容器类data tpye,不支持最基本的int,也不支持动态访问,要么方法不一致,自然是不合适的。


    也可以继承collections里的UserDict。UserDict中data属性是dict,其他方法都模仿了 dict

  • 相关阅读:
    ado 查询文件数据库
    S60平台简体汉字处理浅谈转symbian wiki
    symbian在收件箱创建短信(转)
    symbian得到收件箱中未读短信的数目
    enable marquee with the animated in the ListBox
    如何为Series60绘制一个常驻顶端的提示图标 [symbian]
    Symbian 得到左右软键项(CBA)的内容
    asp.net 中如何请求一个其它网站的页面
    使S60程序全屏运行,fullscreen
    symbian程序在后台运行
  • 原文地址:https://www.cnblogs.com/willowj/p/8187927.html
Copyright © 2011-2022 走看看