Я пытаюсь перебрать словарь и распечатать все пары ключ-значение, где значение не является вложенным словарем. Если значение является словарем, я хочу войти в него и распечатать его пары ключ-значение и т.д.
Я пробовал это. Но это работает только для первых двух уровней. Мне нужно, чтобы это работало для любого количества уровней.
for k, v in d.iteritems(): iftype(v) isdict: for t, c in v.iteritems(): print"{0} : {1}".format(t, c)
Я тоже пробовал это. Он по-прежнему печатает только одно.
defprintDict(d): for k, v in d.iteritems(): iftype(v) isdict: printDict(v) else: print"{0} : {1}".format(k, v)
xml : {u'config': {u'portstatus': {u'status': u'good'}, u'target': u'1'}, u'port': u'11'}
Переведено автоматически
Ответ 1
Как сказал Никлас, вам нужна рекурсия, т. Е. вы хотите определить функцию для печати вашего dict , и если значение является dict , вы хотите вызвать свою функцию печати, используя этот новый dict.
Что-то вроде :
defmyprint(d): for k, v in d.items(): ifisinstance(v, dict): myprint(v) else: print("{0} : {1}".format(k, v))
Ответ 2
Существуют потенциальные проблемы, если вы пишете свою собственную рекурсивную реализацию или итеративный эквивалент со stack . Смотрите этот пример.:
В обычном смысле вложенный словарь будет представлять собой n-n-ную древовидную структуру данных. Но определение не исключает возможности перекрестного ребра или даже заднего ребра (таким образом, это больше не дерево). Например, здесь key2.2 относится к словарю из key1, key2.3 указывает на весь словарь (задний край / цикл). При наличии обратного ребра (цикла) стек / рекурсия будет выполняться бесконечно.
По запросу Moundra это способ избежать циклов (DFS):
defmyprint(d): stack = list(d.items()) visited = set() while stack: k, v = stack.pop() ifisinstance(v, dict): if k notin visited: stack.extend(v.items()) else: print("%s: %s" % (k, v)) visited.add(k)
Ответ 3
Поскольку a dict является итерабельным, вы можете применить классическую формулу итерации вложенного контейнера к этой проблеме всего с парой незначительных изменений. Вот версия Python 2 (см. Ниже 3):
import collections defnested_dict_iter(nested): for key, value in nested.iteritems(): ifisinstance(value, collections.Mapping): for inner_key, inner_value in nested_dict_iter(value): yield inner_key, inner_value else: yield key, value
В Python 2 может быть возможно создать пользовательский параметр, Mapping который квалифицируется как Mapping но не содержит iteritems, и в этом случае это приведет к сбою. В документах не указано, что iteritems требуется для Mapping; с другой стороны, источник предоставляет Mapping типам iteritems метод. Итак, для пользовательского Mappings наследования от collections.Mapping явно на всякий случай.
В Python 3 необходимо внести ряд улучшений. Начиная с Python 3.3, абстрактные базовые классы существуют в collections.abc. Они также остаются в collections для обратной совместимости, но лучше, когда наши абстрактные базовые классы собраны в одном пространстве имен. Итак, это импортируется abc из collections. Python 3.3 также добавляет yield from, который предназначен именно для таких ситуаций. Это не пустой синтаксический сахар; это может привести к более быстрому коду и более разумному взаимодействию с сопрограммами.
from collections import abc defnested_dict_iter(nested): for key, value in nested.items(): ifisinstance(value, abc.Mapping): yieldfrom nested_dict_iter(value) else: yield key, value
Ответ 4
Альтернативное итеративное решение:
defmyprint(d): stack = d.items() while stack: k, v = stack.pop() ifisinstance(v, dict): stack.extend(v.iteritems()) else: print("%s: %s" % (k, v))