Я ищу элегантный способ получить данные, используя доступ к атрибутам на dict с некоторыми вложенными dicts и списками (то есть синтаксис объекта в стиле 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
Я думаю, это невозможно без рекурсии, но что было бы хорошим способом получить стиль объекта для диктов?
python
object
dictionary
Марк
источник
источник
from_
а не в_from
соответствии с ОПТОСОЗ 8 .getattr(x, 'from')
вместо переименования атрибута.d1.b.c
), я думаю, ясно, что вы должны использовать что-то из библиотеки, например namedtuple из коллекций , как предполагает этот ответ , .. .Ответы:
Обновление: в Python 2.6 и более поздних версиях подумайте, соответствует ли
namedtuple
структура данных вашим потребностям:Альтернатива (оригинальное содержание ответа):
Затем вы можете использовать:
источник
Struct
s из вложенных словарей, но в целом тип значения может быть любым. Ключ ограничен тем, чтобы быть подходящим для слота объектаargparse.Namespace
(которые также определенных__eq__
,__ne__
,__contains__
).источник
if isinstance(b, (list, tuple)):
obj
наследование классаargparse.Namespace
для дополнительных функций, таких как читаемое строковое представление.Удивительно, но никто не упомянул Банча . Эта библиотека предназначена исключительно для предоставления доступа к объектам dict в стиле атрибутов и выполняет именно то, что хочет OP. Демонстрация:
Библиотека Python 3 доступна по адресу https://github.com/Infinidat/munch - Кредит переходит на codyzu
источник
затем добавьте рекурсию к этому, и все готово.
отредактируйте это так, как я бы это реализовал:
источник
top_instance = top()
и вернуть туда, куда вы вернетесьtop
?x
иx.b
возвращающие некрасиво<class '__main__.new'>
Есть помощник коллекции
namedtuple
, который может сделать это для вас:источник
Может использоваться с любой структурой последовательности / dict / value любой глубины.
источник
def __repr__(self): return '{%s}' % str(', '.join("'%s': %s" % (k, repr(v)) for (k, v) in self.__dict__.iteritems()))
.items()
вместо.iteritems()
строки 4. (Функция была переименована, но делает то же самое )Взяв то, что я чувствую, являются лучшими аспектами предыдущих примеров, вот что я придумал:
источник
def __init__(self, dct): for k, v in dct.iteritems(): setattr(self, k, isinstance(v, dict) and self.__class__(v) or v)
который также удаляет явный вызовStruct
isinstance(v, dict)
проверка будет лучше,isinstance(v, collections.Mapping)
так что он может обрабатывать будущее ДИКТ подобные вещиЕсли ваш dict исходит из
json.loads()
, вы можете вместо этого превратить его в объект (а не в dict) в одну строку:Смотрите также Как преобразовать данные JSON в объект Python .
источник
.loads
если у вас есть огромный объект JSONЕсли вы хотите получить доступ к ключам dict как к объекту (или как к dict для сложных ключей), сделать это рекурсивно, а также иметь возможность обновить исходный dict, вы можете сделать следующее:
Пример использования:
источник
источник
Я закончил тем, что пытался ОБА AttrDict и Букетбиблиотеки и обнаружили, что они слишком медленные для моего использования. После того, как мы с другом посмотрели на него, мы обнаружили, что основной метод написания этих библиотек приводит к агрессивной рекурсии библиотеки через вложенный объект и копированию объекта словаря. Имея это в виду, мы сделали два ключевых изменения. 1) Мы сделали атрибуты с отложенной загрузкой 2) вместо создания копий словарного объекта, мы создаем копии легкого прокси-объекта. Это окончательная реализация. Увеличение производительности при использовании этого кода невероятно. При использовании AttrDict или Bunch только эти две библиотеки потребляли 1/2 и 1/3 соответственно моего времени запроса (что !?). Этот код сократил это время практически до нуля (где-то в диапазоне 0,5 мс). Это, конечно, зависит от ваших потребностей,
Смотрите оригинальную реализацию здесь по адресу https://stackoverflow.com/users/704327/michael-merickel .
Следует также отметить, что эта реализация довольно проста и не реализует все методы, которые могут вам понадобиться. Вам нужно будет написать их, как требуется, для объектов DictProxy или ListProxy.
источник
x.__dict__.update(d)
должно быть хорошо.источник
__dict__
: попробуйте,object().__dict__
и вы получитеAttributeError: 'object' object has no attribute '__dict__'
Вы можете использовать
json
модуль стандартной библиотеки с пользовательским хуком объектов :Пример использования:
И это не только для чтения, как это происходит
namedtuple
, то есть вы можете изменять значения, а не структуру:источник
json.JSONEncoder
иobject_hook
.Это должно начать ваше:
Это не работает для списков, пока. Вам придется обернуть списки в UserList и перегружать,
__getitem__
чтобы обернуть слова.источник
if isinstance(d, list)
предложение fromAnon
's answer.Я знаю, что здесь уже есть много ответов, и я опаздываю на вечеринку, но этот метод рекурсивно и «на месте» преобразует словарь в объектоподобную структуру ... Работает в 3.xx
источник
источник
Позвольте мне объяснить решение, которое я почти использовал некоторое время назад. Но сначала причина, по которой я этого не сделал, иллюстрируется тем, что следующий код:
дает эту ошибку:
Поскольку «from» является ключевым словом Python, существуют определенные словарные ключи, которые вы не можете разрешить.
Теперь мое решение позволяет получить доступ к элементам словаря, используя их имена напрямую. Но это также позволяет использовать «словарную семантику». Вот код с примером использования:
источник
Старые вопросы и ответы, но у меня есть кое-что еще, чтобы поговорить. Кажется, никто не говорит о рекурсивных диктовках. Это мой код:
источник
Хотел загрузить мою версию этой маленькой парадигмы.
Он сохраняет атрибуты для типа, который импортируется в класс. Мое единственное беспокойство будет переписывать методы из словаря вашего анализа. Но в остальном кажется солидным!
источник
df.a
даже не работает.Это тоже хорошо работает
источник
Вот еще один способ реализовать оригинальное предложение SilentGhost:
источник
Я наткнулся на случай, когда мне нужно было рекурсивно преобразовать список диктов в список объектов, поэтому, основываясь на фрагменте Роберто, вот что сработало для меня:
Обратите внимание, что любой кортеж будет преобразован в эквивалент списка по очевидным причинам.
Надеюсь, это поможет кому-то так же, как все ваши ответы для меня, ребята.
источник
Как насчет просто назначения вашего
dict
на__dict__
пустой объект?Конечно, это не работает на вашем примере с вложенным диктом, если вы не выполняете рекурсивную рекурсивную процедуру:
И ваш примерный элемент списка, вероятно, должен был представлять
Mapping
собой список пар (ключ, значение), например:источник
Вот еще одна реализация:
[Edit] Пропущено немного о том, как обрабатывать дикты в списках, а не только другие. Добавлено исправление.
источник
Применение:
источник
Как насчет этого:
Это может быть использовано следующим образом:
источник
Я думаю, что dict состоит из числа, строки и dict достаточно времени. Поэтому я игнорирую ситуацию, когда кортежи, списки и другие типы не появляются в конечном измерении слова.
Учитывая наследование в сочетании с рекурсией, он удобно решает проблему печати, а также предоставляет два способа запроса данных, один способ редактирования данных.
Посмотрите на приведенный ниже пример, который описывает некоторую информацию о студентах:
Результаты:
источник
Обычно вы хотите отразить иерархию диктов в вашем объекте, но не список или кортежи, которые обычно находятся на самом низком уровне. Вот как я это сделал:
Итак, мы делаем:
и получить:
x.b.b1.x
1x.c
['привет', 'бар']источник
Мой словарь имеет этот формат:
Как видно, у меня есть вложенные словари и список диктов . Это связано с тем, что addr_bk был декодирован из данных буфера протокола, которые были преобразованы в python dict с использованием lwpb.codec. Есть необязательное поле (например, email =>, где ключ может быть недоступен) и повторяемое поле (например, phone =>, преобразованное в список dict).
Я перепробовал все предложенные выше решения. Некоторые плохо обрабатывают вложенные словари. Другие не могут легко распечатать детали объекта.
Только решение, dict2obj (dict) от Dawie Strauss, работает лучше всего.
Я немного улучшил его, когда ключ не может быть найден:
Затем я проверил это с:
источник
Основываясь на моем ответе на « python: Как динамически добавить свойство в класс? »:
Вы вызываете
makedata
словарь, который хотите преобразовать, или, может быть, вtrydata
зависимости от того, что вы ожидаете в качестве ввода, и он выплевывает объект данных.Ноты:
trydata
если вам нужно больше функциональности.x.a = {}
или подобное.источник