如何定义超强大的类样式dict对象? [英] How to define a super powerful class-style dict object?

查看:48
本文介绍了如何定义超强大的类样式dict对象?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

假定满足我需要的对象称为 classdic ,则类 classdic 的实例的功能为:

Assume that the object meeting my need is called classdic, then the functions of an instance of class classdic are:


  1. 查询,更新,添加和删除数据都可以用类样式和dict样式来实现(称为两种方式。

  1. Query, update, add, and delete data can be all realized in class style way and dict style way (called "two ways").

当属性或键不存在时,classdic实例可以自动构建该属性或使其等于两个实例的默认值和字典,因此我们可以用两种方式查询它(注意:不添加,只查询)。

When an attribute or a key not existing, the instance of classdic can automatically build it and make it equal the default value on both instance and dict, thus we can query it both ways (note: not add, just query).

所以,如何我可以实现该类吗?

So, how can I implement this class?

下面的示例显示了该类的实例如何工作:

The example below shows how an instance of this class would work:

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

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

This will not automatically create nested instances of itself; you'll need to loop over the input dictionary and create nested objects yourself.

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

But it does offer attribute access and default values:

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

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

To build your tree from an existing dictionary, use the from_dictionaries() class method:

>>> 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

请注意,字典上的键可以掩码方法;在插入与字典方法匹配的键时,请记住以下几点:

Note that keys on the dictionary can mask methods; keep that in mind when inserting keys that match dictionary methods:

>>> 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

这篇关于如何定义超强大的类样式dict对象?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆