在python中覆盖{}

时间:2012-01-03 09:12:07

标签: python dictionary overwrite

我想创建一个dict int,你可以像这样访问:

>>> my_dict["property'] = 3
>>> my_dict.property
3

所以我做了这个:

class DictAsMember(dict):
    def __getattr__(self, name):
        return self[name]

这样可以正常工作,但是如果你有嵌套的dicts它不起作用,例如:

my_dict = DictAsMember()
my_dict["property"] = {'sub': 1}

我可以访问my_dict.property但是逻辑上我不能做my_dict.property.sub因为属性是默认的dict,所以我想要它覆盖默认的dict,所以你可以使用{}。

这可能吗?

2 个答案:

答案 0 :(得分:7)

问题的一个解决方法是在使用DictAsMember方法返回默认词典之前使用__getattr__包装默认词典:

class DictAsMember(dict):
    def __getattr__(self, name):
        value = self[name]
        if isinstance(value, dict):
            value = DictAsMember(value)
        elif isinstance(value, list):
            value = [DictAsMember(element)
                     if isinstance(element, dict)
                     else element
                     for element in value]

        return value

my_dict = DictAsMember()
my_dict["property"] = {'sub': 1}
print my_dict.property.sub    # 1 will be printed

my_dict = DictAsMember()
my_dict["property"] = [{'name': 1}, {'name': 2}]
print my_dict.property[1].name    # 2 will be printed

答案 1 :(得分:2)

您可以改为使用命名元组,而不是编写自己的类来实现my_dict.property表示法(这称为对象表示法)。可以使用变量引用等对象或标准元组语法来引用命名元组。来自documentation

  

[named tuple]用于创建可访问字段的类似元组的对象   通过属性查找以及可索引和可​​迭代。

作为其使用的一个例子:

from collections import *

my_structure = namedtuple('my_structure', ['name', 'property'])
my_property  = namedtuple('my_property', ['sub'])

s = my_structure('fred', my_property(1))

s # my_structure(name='fred', property=my_property(sub=1)) will be printed

s.name # 'fred' will be printed

s.property # my_property(sub=1) will be printed

s.property.sub # 1 will be printed

另请参阅this question的已接受答案,以获得有关命名元组的精彩摘要。