중첩 된 dicts 및 list가있는 dict의 속성 액세스를 사용하여 데이터를 얻는 우아한 방법을 찾고 있습니다 (예 : javascript 스타일 객체 구문).
예를 들면 다음과 같습니다.
>>> d = {'a': 1, 'b': {'c': 2}, 'd': ["hi", {'foo': "bar"}]}
이 방법으로 액세스 할 수 있어야합니다.
>>> x = dict2obj(d)
>>> x.a
1
>>> x.b.c
2
>>> x.d[1].foo
bar
나는 이것이 재귀 없이는 불가능하다고 생각하지만 dicts에 대한 객체 스타일을 얻는 좋은 방법은 무엇입니까?
답변
업데이트 : Python 2.6 이상에서 namedtuple
데이터 구조가 요구 사항에 적합한 지 고려 하십시오.
>>> from collections import namedtuple
>>> MyStruct = namedtuple('MyStruct', 'a b d')
>>> s = MyStruct(a=1, b={'c': 2}, d=['hi'])
>>> s
MyStruct(a=1, b={'c': 2}, d=['hi'])
>>> s.a
1
>>> s.b
{'c': 2}
>>> s.c
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
AttributeError: 'MyStruct' object has no attribute 'c'
>>> s.d
['hi']
대안 (원래 답변 내용)은 다음과 같습니다.
class Struct:
def __init__(self, **entries):
self.__dict__.update(entries)
그런 다음 다음을 사용할 수 있습니다.
>>> args = {'a': 1, 'b': 2}
>>> s = Struct(**args)
>>> s
<__main__.Struct instance at 0x01D6A738>
>>> s.a
1
>>> s.b
2
답변
class obj(object):
def __init__(self, d):
for a, b in d.items():
if isinstance(b, (list, tuple)):
setattr(self, a, [obj(x) if isinstance(x, dict) else x for x in b])
else:
setattr(self, a, obj(b) if isinstance(b, dict) else b)
>>> d = {'a': 1, 'b': {'c': 2}, 'd': ["hi", {'foo': "bar"}]}
>>> x = obj(d)
>>> x.b.c
2
>>> x.d[1].foo
'bar'
답변
놀랍게도 아무도 Bunch에 대해 언급하지 않았습니다 . 이 라이브러리는 독점적으로 dict 객체에 대한 속성 스타일 액세스를 제공하고 OP가 원하는 것을 정확하게 수행합니다. 데모 :
>>> from bunch import bunchify
>>> d = {'a': 1, 'b': {'c': 2}, 'd': ["hi", {'foo': "bar"}]}
>>> x = bunchify(d)
>>> x.a
1
>>> x.b.c
2
>>> x.d[1].foo
'bar'
Python 3 라이브러리는 https://github.com/Infinidat/munch에 있습니다. 크레딧은 codyzu 로 이동합니다
답변
x = type('new_dict', (object,), d)
그런 다음 재귀를 추가하면 완료됩니다.
이것을 구현하는 방법을 편집 하십시오.
>>> d
{'a': 1, 'b': {'c': 2}, 'd': ['hi', {'foo': 'bar'}]}
>>> def obj_dic(d):
top = type('new', (object,), d)
seqs = tuple, list, set, frozenset
for i, j in d.items():
if isinstance(j, dict):
setattr(top, i, obj_dic(j))
elif isinstance(j, seqs):
setattr(top, i,
type(j)(obj_dic(sj) if isinstance(sj, dict) else sj for sj in j))
else:
setattr(top, i, j)
return top
>>> x = obj_dic(d)
>>> x.a
1
>>> x.b.c
2
>>> x.d[1].foo
'bar'
답변
이라는 컬렉션 도우미 namedtuple
가 있습니다.
from collections import namedtuple
d_named = namedtuple('Struct', d.keys())(*d.values())
In [7]: d_named
Out[7]: Struct(a=1, b={'c': 2}, d=['hi', {'foo': 'bar'}])
In [8]: d_named.a
Out[8]: 1
답변
class Struct(object):
"""Comment removed"""
def __init__(self, data):
for name, value in data.iteritems():
setattr(self, name, self._wrap(value))
def _wrap(self, value):
if isinstance(value, (tuple, list, set, frozenset)):
return type(value)([self._wrap(v) for v in value])
else:
return Struct(value) if isinstance(value, dict) else value
모든 깊이의 시퀀스 / dict / value 구조와 함께 사용할 수 있습니다.
답변
필자가 이전 예제의 가장 좋은 측면이라고 생각하는 것을 생각해 봅시다.
class Struct:
'''The recursive class for building and representing objects with.'''
def __init__(self, obj):
for k, v in obj.iteritems():
if isinstance(v, dict):
setattr(self, k, Struct(v))
else:
setattr(self, k, v)
def __getitem__(self, val):
return self.__dict__[val]
def __repr__(self):
return '{%s}' % str(', '.join('%s : %s' % (k, repr(v)) for
(k, v) in self.__dict__.iteritems()))