Как красиво распечатать вложенные словари? - PullRequest
225 голосов
/ 12 июля 2010

Как я могу довольно напечатать словарь с глубиной ~ 4 в Python? Я попробовал красивую печать с pprint(), но это не сработало:

import pprint 
pp = pprint.PrettyPrinter(indent=4)
pp.pprint(mydict)

Я просто хочу отступ ("\t") для каждого вложения, чтобы я получил что-то вроде этого:

key1
    value1
    value2
    key2
       value1
       value2

и т.д..

Как я могу это сделать?

Ответы [ 17 ]

426 голосов
/ 23 июля 2010

Моей первой мыслью было, что сериализатор JSON, вероятно, довольно хорош во вложенных словарях, поэтому я бы обманул и использовал это:

>>> import json
>>> print json.dumps({'a':2, 'b':{'x':3, 'y':{'t1': 4, 't2':5}}},
...                  sort_keys=True, indent=4)
{
    "a": 2,
    "b": {
        "x": 3,
        "y": {
            "t1": 4,
            "t2": 5
        }
    }
}
117 голосов
/ 12 июля 2010

Я не уверен, как именно вы хотите, чтобы форматирование выглядело, но вы могли бы начать с такой функции:

def pretty(d, indent=0):
   for key, value in d.items():
      print('\t' * indent + str(key))
      if isinstance(value, dict):
         pretty(value, indent+1)
      else:
         print('\t' * (indent+1) + str(value))
41 голосов
/ 15 февраля 2013

Вы можете попробовать YAML через PyYAML .Его выход может быть точно настроен.Я бы предложил начать со следующего:

print yaml.dump(data, allow_unicode=True, default_flow_style=False)

Результат очень читабельный;при необходимости его также можно проанализировать обратно в Python.

Редактировать:

Пример:

>>> import yaml
>>> data = {'a':2, 'b':{'x':3, 'y':{'t1': 4, 't2':5}}}
>>> print yaml.dump(data, default_flow_style=False)
a: 2
b:
  x: 3
  y:
    t1: 4
    t2: 5
32 голосов
/ 06 октября 2014

Что касается того, что было сделано, я не вижу симпатичного принтера, который, по крайней мере, имитировал бы вывод интерпретатора python с очень простым форматированием, так что вот мое:

class Formatter(object):
    def __init__(self):
        self.types = {}
        self.htchar = '\t'
        self.lfchar = '\n'
        self.indent = 0
        self.set_formater(object, self.__class__.format_object)
        self.set_formater(dict, self.__class__.format_dict)
        self.set_formater(list, self.__class__.format_list)
        self.set_formater(tuple, self.__class__.format_tuple)

    def set_formater(self, obj, callback):
        self.types[obj] = callback

    def __call__(self, value, **args):
        for key in args:
            setattr(self, key, args[key])
        formater = self.types[type(value) if type(value) in self.types else object]
        return formater(self, value, self.indent)

    def format_object(self, value, indent):
        return repr(value)

    def format_dict(self, value, indent):
        items = [
            self.lfchar + self.htchar * (indent + 1) + repr(key) + ': ' +
            (self.types[type(value[key]) if type(value[key]) in self.types else object])(self, value[key], indent + 1)
            for key in value
        ]
        return '{%s}' % (','.join(items) + self.lfchar + self.htchar * indent)

    def format_list(self, value, indent):
        items = [
            self.lfchar + self.htchar * (indent + 1) + (self.types[type(item) if type(item) in self.types else object])(self, item, indent + 1)
            for item in value
        ]
        return '[%s]' % (','.join(items) + self.lfchar + self.htchar * indent)

    def format_tuple(self, value, indent):
        items = [
            self.lfchar + self.htchar * (indent + 1) + (self.types[type(item) if type(item) in self.types else object])(self, item, indent + 1)
            for item in value
        ]
        return '(%s)' % (','.join(items) + self.lfchar + self.htchar * indent)

Для его инициализации:

pretty = Formatter()

Он может поддерживать добавление форматеров для определенных типов, вам просто нужно создать для этого функцию, подобную этой, и связать ее с нужным типом с помощью set_formater:

from collections import OrderedDict

def format_ordereddict(self, value, indent):
    items = [
        self.lfchar + self.htchar * (indent + 1) +
        "(" + repr(key) + ', ' + (self.types[
            type(value[key]) if type(value[key]) in self.types else object
        ])(self, value[key], indent + 1) + ")"
        for key in value
    ]
    return 'OrderedDict([%s])' % (','.join(items) +
           self.lfchar + self.htchar * indent)
pretty.set_formater(OrderedDict, format_ordereddict)

По историческим причинам я сохранил предыдущий симпатичный принтер, который был функцией вместо класса, но они оба могут использоваться одинаково, версия класса просто допускает гораздо больше:

def pretty(value, htchar='\t', lfchar='\n', indent=0):
    nlch = lfchar + htchar * (indent + 1)
    if type(value) is dict:
        items = [
            nlch + repr(key) + ': ' + pretty(value[key], htchar, lfchar, indent + 1)
            for key in value
        ]
        return '{%s}' % (','.join(items) + lfchar + htchar * indent)
    elif type(value) is list:
        items = [
            nlch + pretty(item, htchar, lfchar, indent + 1)
            for item in value
        ]
        return '[%s]' % (','.join(items) + lfchar + htchar * indent)
    elif type(value) is tuple:
        items = [
            nlch + pretty(item, htchar, lfchar, indent + 1)
            for item in value
        ]
        return '(%s)' % (','.join(items) + lfchar + htchar * indent)
    else:
        return repr(value)

Чтобы использовать это:

>>> a = {'list':['a','b',1,2],'dict':{'a':1,2:'b'},'tuple':('a','b',1,2),'function':pretty,'unicode':u'\xa7',("tuple","key"):"valid"}
>>> a
{'function': <function pretty at 0x7fdf555809b0>, 'tuple': ('a', 'b', 1, 2), 'list': ['a', 'b', 1, 2], 'dict': {'a': 1, 2: 'b'}, 'unicode': u'\xa7', ('tuple', 'key'): 'valid'}
>>> print(pretty(a))
{
    'function': <function pretty at 0x7fdf555809b0>,
    'tuple': (
        'a',
        'b',
        1,
        2
    ),
    'list': [
        'a',
        'b',
        1,
        2
    ],
    'dict': {
        'a': 1,
        2: 'b'
    },
    'unicode': u'\xa7',
    ('tuple', 'key'): 'valid'
}

По сравнению с другими версиями:

  • Это решение напрямую ищет тип объекта, поэтому вы можете печатать практически все, не только список или диктовку.
  • Нет зависимости.
  • Все помещено в строку, поэтому вы можете делать с ней все, что захотите.
  • Класс и функция были протестированы и работают с Python 2.7 и 3.4.
  • Вы можете иметь все типы объектов внутри, это их представления, а не их содержимое, которое помещается в результат (поэтому строка имеет кавычки, строка Unicode полностью представлена ​​...).
  • В версии класса вы можете добавить форматирование для каждого типа объекта или изменить его на уже определенные.
  • ключ может быть любого допустимого типа.
  • Символ отступа и символ новой строки можно изменить на все, что нам нужно.
  • Dict, List и Tuple довольно напечатаны.
7 голосов
/ 09 сентября 2018

Другой вариант с yapf:

from pprint import pformat
from yapf.yapflib.yapf_api import FormatCode

dict_example = {'1': '1', '2': '2', '3': [1, 2, 3, 4, 5], '4': {'1': '1', '2': '2', '3': [1, 2, 3, 4, 5]}}
dict_string = pformat(dict_example)
formatted_code, _ = FormatCode(dict_string)

print(formatted_code)

Выход:

{
    '1': '1',
    '2': '2',
    '3': [1, 2, 3, 4, 5],
    '4': {
        '1': '1',
        '2': '2',
        '3': [1, 2, 3, 4, 5]
    }
}
4 голосов
/ 01 декабря 2016

Как уже сообщали другие, вы можете использовать recursion / dfs для печати вложенных данных словаря и вызывать рекурсивно, если это словарь;в противном случае распечатайте данные.

def print_json(data):
    if type(data) == dict:
            for k, v in data.items():
                    print k
                    print_json(v)
    else:
            print data
3 голосов
/ 20 мая 2015

Я взял STH-ответ и немного изменил его, чтобы соответствовать моим потребностям во вложенных словарях и списках:

def pretty(d, indent=0):
    if isinstance(d, dict):
        for key, value in d.iteritems():
            print '\t' * indent + str(key)
            if isinstance(value, dict) or isinstance(value, list):
                pretty(value, indent+1)
            else:
                print '\t' * (indent+1) + str(value)
    elif isinstance(d, list):
        for item in d:
            if isinstance(item, dict) or isinstance(item, list):
                pretty(item, indent+1)
            else:
                print '\t' * (indent+1) + str(item)
    else:
        pass

Который затем дает мне вывод как:

>>> 
xs:schema
    @xmlns:xs
        http://www.w3.org/2001/XMLSchema
    xs:redefine
        @schemaLocation
            base.xsd
        xs:complexType
            @name
                Extension
            xs:complexContent
                xs:restriction
                    @base
                        Extension
                    xs:sequence
                        xs:element
                            @name
                                Policy
                            @minOccurs
                                1
                            xs:complexType
                                xs:sequence
                                    xs:element
                                            ...
2 голосов
/ 09 мая 2019

таким образом, вы можете распечатать его довольно красиво, например, имя вашего словаря - yasin

import json

print (json.dumps(yasin, indent=2))
1 голос
/ 04 января 2019

pout может печатать все, что вы ни бросаете, например (заимствование data из другого ответа):

data = {'a':2, 'b':{'x':3, 'y':{'t1': 4, 't2':5}}}
pout.vs(data)

приведет к выводу на экран, например:

{
    'a': 2,
    'b':
    {
        'y':
        {
            't2': 5,
            't1': 4
        },
        'x': 3
    }
}

или вы можете вернуть форматированную строку вывода вашего объекта:

v = pout.s(data)

Его основной сценарий использования предназначен для отладки, поэтому он не задыхается от экземпляров объектов или чего-либо еще и обрабатывает выходные данные в Unicode, как и следовало ожидать, работает в python 2.7 и 3.

раскрытие : я автор и сопровождающий pout.

1 голос
/ 19 мая 2015
This class prints out a complex nested dictionary with sub dictionaries and sub lists.  
##
## Recursive class to parse and print complex nested dictionary
##

class NestedDictionary(object):
    def __init__(self,value):
        self.value=value

    def print(self,depth):
        spacer="--------------------"
        if type(self.value)==type(dict()):
            for kk, vv in self.value.items():
                if (type(vv)==type(dict())):
                    print(spacer[:depth],kk)
                    vvv=(NestedDictionary(vv))
                    depth=depth+3
                    vvv.print(depth)
                    depth=depth-3
                else:
                    if (type(vv)==type(list())):
                        for i in vv:
                            vvv=(NestedDictionary(i))
                            depth=depth+3
                            vvv.print(depth)
                            depth=depth-3
                    else:
                        print(spacer[:depth],kk,vv) 

##
## Instatiate and execute - this prints complex nested dictionaries
## with sub dictionaries and sub lists
## 'something' is a complex nested dictionary

MyNest=NestedDictionary(weather_com_result)
MyNest.print(0)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...