我如何使Python字典成员访问通过点“。”?

例如,我想写mydict.val而不是mydict['val']。

我还想以这种方式访问嵌套字典。例如

mydict.mydict2.val 

会提到

mydict = { 'mydict2': { 'val': ... } }

当前回答

我喜欢Munch,它提供了很多方便的选项在点访问。

进口蒙克 Temp_1 = {'person': {' fname': 'senthil', 'lname': 'ramalingam'}} Dict_munch = munch.munchify(temp_1) dict_munch.person.fname

其他回答

通过pip安装dotmap

pip install dotmap

它能做你想让它做的所有事情,并继承dict的子类,所以它的操作就像一个普通的字典:

from dotmap import DotMap

m = DotMap()
m.hello = 'world'
m.hello
m.hello += '!'
# m.hello and m['hello'] now both return 'world!'
m.val = 5
m.val2 = 'Sam'

最重要的是,你可以将它转换为dict对象:

d = m.toDict()
m = DotMap(d) # automatic conversion in constructor

这意味着如果你想访问的东西已经是字典形式的,你可以把它转换成DotMap来方便访问:

import json
jsonDict = json.loads(text)
data = DotMap(jsonDict)
print data.location.city

最后,它会自动创建新的子DotMap实例,你可以这样做:

m = DotMap()
m.people.steve.age = 31

与Bunch的比较

完全公开:我是DotMap的创造者。我创建它是因为Bunch缺少这些功能

记住添加的顺序项并按此顺序迭代 自动创建子DotMap,当你有很多层次结构时,这节省了时间,并使代码更干净 从字典构造并递归地将所有子字典实例转换为DotMap

不是对OP问题的直接回答,但受到启发,也许对一些人有用。我已经创建了一个基于对象的解决方案使用内部__dict__(在任何方式优化代码)

payload = {
    "name": "John",
    "location": {
        "lat": 53.12312312,
        "long": 43.21345112
    },
    "numbers": [
        {
            "role": "home",
            "number": "070-12345678"
        },
        {
            "role": "office",
            "number": "070-12345679"
        }
    ]
}


class Map(object):
    """
    Dot style access to object members, access raw values
    with an underscore e.g.

    class Foo(Map):
        def foo(self):
            return self.get('foo') + 'bar'

    obj = Foo(**{'foo': 'foo'})

    obj.foo => 'foobar'
    obj._foo => 'foo'

    """

    def __init__(self, *args, **kwargs):
        for arg in args:
            if isinstance(arg, dict):
                for k, v in arg.iteritems():
                    self.__dict__[k] = v
                    self.__dict__['_' + k] = v

        if kwargs:
            for k, v in kwargs.iteritems():
                self.__dict__[k] = v
                self.__dict__['_' + k] = v

    def __getattribute__(self, attr):
        if hasattr(self, 'get_' + attr):
            return object.__getattribute__(self, 'get_' + attr)()
        else:
            return object.__getattribute__(self, attr)

    def get(self, key):
        try:
            return self.__dict__.get('get_' + key)()
        except (AttributeError, TypeError):
            return self.__dict__.get(key)

    def __repr__(self):
        return u"<{name} object>".format(
            name=self.__class__.__name__
        )


class Number(Map):
    def get_role(self):
        return self.get('role')

    def get_number(self):
        return self.get('number')


class Location(Map):
    def get_latitude(self):
        return self.get('lat') + 1

    def get_longitude(self):
        return self.get('long') + 1


class Item(Map):
    def get_name(self):
        return self.get('name') + " Doe"

    def get_location(self):
        return Location(**self.get('location'))

    def get_numbers(self):
        return [Number(**n) for n in self.get('numbers')]


# Tests

obj = Item({'foo': 'bar'}, **payload)

assert type(obj) == Item
assert obj._name == "John"
assert obj.name == "John Doe"
assert type(obj.location) == Location
assert obj.location._lat == 53.12312312
assert obj.location._long == 43.21345112
assert obj.location.latitude == 54.12312312
assert obj.location.longitude == 44.21345112

for n in obj.numbers:
    assert type(n) == Number
    if n.role == 'home':
        assert n.number == "070-12345678"
    if n.role == 'office':
        assert n.number == "070-12345679"

可以使用dotsi来支持完整列表、dict和递归,并使用一些扩展方法

pip install dotsi

and

>>> import dotsi
>>> 
>>> d = dotsi.Dict({"foo": {"bar": "baz"}})     # Basic
>>> d.foo.bar
'baz'
>>> d.users = [{"id": 0, "name": "Alice"}]   # List
>>> d.users[0].name
'Alice'
>>> d.users.append({"id": 1, "name": "Becca"}); # Append
>>> d.users[1].name
'Becca'
>>> d.users += [{"id": 2, "name": "Cathy"}];    # `+=`
>>> d.users[2].name
'Cathy'
>>> d.update({"tasks": [{"id": "a", "text": "Task A"}]});
>>> d.tasks[0].text
'Task A'
>>> d.tasks[0].tags = ["red", "white", "blue"];
>>> d.tasks[0].tags[2];
'blue'
>>> d.tasks[0].pop("tags")                      # `.pop()`
['red', 'white', 'blue']
>>> 
>>> import pprint
>>> pprint.pprint(d)
{'foo': {'bar': 'baz'},
 'tasks': [{'id': 'a', 'text': 'Task A'}],
 'users': [{'id': 0, 'name': 'Alice'},
           {'id': 1, 'name': 'Becca'},
           {'id': 2, 'name': 'Cathy'}]}
>>> 
>>> type(d.users)       # dotsi.Dict (AKA dotsi.DotsiDict)
<class 'dotsi.DotsiList'>
>>> type(d.users[0])    # dotsi.List (AKA dotsi.DotsiList)
<class 'dotsi.DotsiDict'> 
>>> 

不喜欢。在Python中,属性访问和索引是分开的事情,您不应该希望它们执行相同的操作。创建一个类(可能是由namedtuple创建的),如果你有一些应该具有可访问属性的东西,并使用[]符号从字典中获取一个项。

获得点访问(但不是数组访问)的一个简单方法是在Python中使用一个普通对象。是这样的:

class YourObject:
    def __init__(self, *args, **kwargs):
        for k, v in kwargs.items():
            setattr(self, k, v)

...像这样使用它:

>>> obj = YourObject(key="value")
>>> print(obj.key)
"value"

... 把它转换成字典:

>>> print(obj.__dict__)
{"key": "value"}