python - 如何定义一个 super 强大的class风格的dict对象?

标签 python class

假设满足我需求的对象叫做classdic,那么类classdic的一个实例的功能是:

  1. 查询、更新、添加、删除数据都可以通过类方式和字典方式实现(称为“两种方式”)。

  2. 当一个属性或键不存在时,classdic的实例可以自动构建它并使它等于instance和dict上的默认值,因此我们可以双向查询(注意:不是添加,只是查询)。

那么,我该如何实现这个类呢?

下面的例子展示了这个类的一个实例是如何工作的:

dic={'one':1,
'two':{'four':4,'five':{'six':6,'seven':7}},
'three':3}

cdic=classdic(dic,default=100)

-------------------query in two 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 two ways-------------------------------------------
>>> cdic['two']['five']['six']=7
>>> cdic.two.five.six
7
>>> cdic.two.five.six=8
>>> cdic['two']['five']['six']
8
-------------------add in two ways-------------------------------------------
>>> cdic['two']['five']['eight']=8
>>> cdic.two.five.eight
8
>>> cdic.two.five.nine=9
>>> cdic['two']['five']['nine']
9
-------------------query default in two 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}

最佳答案

子类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)
        for key, value in d.iteritems():
            if isinstance(value, Mapping):
               value = cls.from_dictionaries(value, default=default)
            cdic[key] = value
        return cdic

这将不会自动创建自身的嵌套实例;您需要遍历输入字典并自己创建嵌套对象。

但它确实提供属性访问和默认值:

>>> cdic = default_attribute_dict(lambda: 100)
>>> cdic.hundred
100
>>> cdic['ten'] = 10
>>> cdic.ten
10
>>> cdic['ten']
10

要从现有字典构建树,请使用 from_dictionaries() 类方法:

>>> cdic = default_attribute_dict.from_dictionaries(dic, default=lambda: 100)
>>> cdic
defaultdict(<function <lambda> at 0x109998848>, {'one': 1, 'three': 3, 'two': defaultdict(<function <lambda> at 0x109998848>, {'four': 4, 'five': defaultdict(<function <lambda> at 0x109998848>, {'seven': 7, 'six': 6})})})
>>> cdic.two.four
4

请注意字典中的键可以屏蔽方法;在插入与字典方法匹配的键时请记住这一点:

>>> cdic = default_attribute_dict.from_dictionaries(dic, default=lambda: 100)
>>> cdic.keys
<built-in method keys of default_attribute_dict object at 0x7fdd0bcc9ac0>
>>> cdic['keys']
100
>>> cdic.keys
100
>>> cdic.keys()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: 'int' object is not callable

关于python - 如何定义一个 super 强大的class风格的dict对象?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19221965/

相关文章:

c++ - 表示类中日期的最佳方式(日月年与时间戳)

python - 加载时未找到 Pickle 文件

python - 类方法生成 "TypeError: ... got multiple values for keyword argument ..."

python - 从多个列表创建唯一的对象列表

python - 生成随机转移概率矩阵python

python - 类变量引用本身?

R 将变量类型从向量分配给大型 data.frame

c++ - 在 C++ 中编写通用堆栈类

python - BeautifulSoup 内部html?

python - 如何使用 Pandas 创建仅包含结果的 Excel 文件?