如何漂亮地打印嵌套字典?

Posted

技术标签:

【中文标题】如何漂亮地打印嵌套字典?【英文标题】:How to pretty print nested dictionaries? 【发布时间】:2011-03-14 20:27:25 【问题描述】:

如何在 Python 中漂亮地打印深度约为 4 的字典?我尝试使用pprint() 进行漂亮的打印,但没有成功:

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

我只是想为每个嵌套使用一个缩进 ("\t"),这样我就会得到这样的结果:

key1
    value1
    value2
    key2
       value1
       value2

等等。

我该怎么做?

【问题讨论】:

“没用”是什么意思?请非常准确地说明 pprint 如何“不起作用”。 我现在已经使用了其中的 3 个答案(每个答案在特定场景中都很好):@Ken's json answer 很好,但有时当对象不能被 json 序列化(抛出异常)时会失败。如果@Ken 的 json 答案不起作用,请尝试 @Andy's yaml answer,它应该可以工作,但字符串输出的可读性较差。 [@sth's answer] 是最通用的(应该​​适用于任何对象并且不使用任何库)。 我认为您应该尝试找到合适的width 参数。查看description 漂亮的打印有什么问题? import pprint.pprint as pprint;pprint(d)? 【参考方案1】:

我的第一个想法是 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
        
    

【讨论】:

这很酷,但不能很好地打印所有字典。 print json.dumps(myObject.__dict__, sort_keys=True, indent=4) #TypeError: is not JSON serializable 虽然这看起来很有用,但它的输出并不是 OP 想要的。 @martineau:OP 请求的输出没有意义,字典需要每个值的键。 @naught101:漂亮的打印机可以做任何需要的事情来产生所需的输出。 json.dumps 将转换函数作为可选参数,因此使用 json.dumps(myObject.__dict__, sort_keys=True, indent=4, deault=str) 您至少可以使用对象实现repr 打印自身并绕过“不可 JSON 序列化”类型错误【参考方案2】:

我不确定您希望格式的外观如何,但您可以从这样的函数开始:

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))

【讨论】:

你知道@Ken 的常规答案比这要好得多。 Json 已经处理了所有事情,这可能会产生以下错误:UnicodeEncodeError: 'ascii' codec can't encode character u'\xf3' in position 50: ordinal not in range(128) 我不能让它与我的解决方案的嵌套字典一起工作,因为它给了我一个 UnicodeEncodeError,它也不打印字典键,不要进入列表和元组,不要' t 保持 python 有效的语法。 这个答案对我来说很有吸引力,但是我发布了一个新问题***.com/questions/36972225/…,它限制了应该打印多少个值。 相当不错。如果您有像 OP 问题中的嵌套列表,则需要为此添加一些处理。如果您在 Py2 中遇到问题,这是因为如果没有答案现在提到的 __future__ 之类的黑客,它就无法正确处理 Unicode,因此您必须在需要的地方使用那些(或已经更新到 3)。 这对我来说已经足够好了:python def pretty(d, indent=0): for key, value in d.items(): if isinstance(value, dict): print(' ' * indent + str(key)) pretty(value, indent+1) else: print(' ' * (indent+1) + f"key: value") 【参考方案3】:

您可以通过PyYAML 尝试YAML。它的输出可以微调。我建议从以下内容开始:

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

【讨论】:

使用 yaml 非常有趣,因为它保留了数据类型而不是其格式,我唯一可以反对的是它不会产生有效的 python 字符串,但几乎可以在 python 中转换回来. yaml 不喜欢 Numpy 的标量类型版本...我并不惊讶它不支持 numpy 数组,但我希望 floatnumpy.float64 这种方法也适用于我使用字典列表【参考方案4】:

通过这种方式,您可以以漂亮的方式打印它,例如您的字典名称是yasin

import json

print (json.dumps(yasin, indent=2))

或者,更安全:

print (json.dumps(yasin, indent=2, default=str))

【讨论】:

这假设字典的内容是 json 可序列化的,这不一定是真的。 @SpiXel。我喜欢 Juan-Kabbali 的回答......但只是为了回答你的观点,你可以去:print (json.dumps(yasin, indent=2, default=str)):任何“毛茸茸”的东西都会用str 函数处理。 这解决了我的“User 类型的对象不是 JSON 可序列化对象”的问题【参考方案5】:

就已经完成的工作而言,我没有看到任何漂亮的打印机至少可以用非常简单的格式模仿 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 的打印效果非常好。

【讨论】:

这绝对应该是公认的解决方案 - 对 JSON 的依赖性很大。 如果它可以通过将对象转换为字典并将其键设置为对象类型来处理对象,那就太棒了 您基本上可以在内部或外部替换 format_object 方法来做到这一点。 set_formater - 需要两个t,这是一个错字,应该是formatter【参考方案6】:

最 Python 的方法之一是使用已构建的 pprint 模块。

定义打印深度所需的参数如您所料depth

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

就是这样!

【讨论】:

更适合快速自省:from pprinit import pprint; pprint(mydict) 供任何人将来使用,@mikezter 的贡献中有一个次要类型。应该是:from pprint import pprint; pprint(mydict) 但是我的刷新到文件不再起作用了:(` pprint(msg, file=self.args.log_root / log_file_name, flush=flush) ` depth 是做什么的? @CharlieParker depth 指定检查的嵌套对象的深度。 (例如 dict(a=dict(b=dict(c=1)))depth=2 打印 'a': 'b': ...depth=1 你得到 'a': ...【参考方案7】:

我还必须传递default 参数,如下所示:

print(json.dumps(my_dictionary, indent=4, default=str))

如果你想对键进行排序,那么你可以这样做:

print(json.dumps(my_dictionary, sort_keys=True, indent=4, default=str))

为了修复这种类型的错误:

TypeError: Object of type 'datetime' is not JSON serializable

这是由于日期时间是字典中的某些值造成的。

【讨论】:

对原答案的改进很棒,感谢您的跟进!【参考方案8】:

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]
    

【讨论】:

此解决方案假定默认安装了yapf,但事实并非如此。你可以安装它pip install yapf。如果你使用 conda conda install yapf 当您的字典中有非 JSON 键时非常有用,例如元组。 既然可以使用repr,为什么还要使用pformat来序列化字典呢?由于yafp实际上是格式化程序,它只需要一个字符串。【参考方案9】:

正如其他人所发布的,您可以使用recursion/dfs来打印嵌套的字典数据,如果是字典则递归调用;否则打印数据。

def print_json(data):
    if type(data) == dict:
            for k, v in data.items():
                    print k
                    print_json(v)
    else:
            print data

【讨论】:

【参考方案10】:

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 的作者和维护者。

【讨论】:

不幸的是,不能在 Windows 上工作,如果你能清楚地显示支持的系统会很好 @Mandera 如果您可以在github.com/Jaymon/pout/issues 上打开问题并提供详细信息,因为我想不出任何原因导致它无法在 Windows 上运行,我们可以在那里继续对话 哦,当然!假设您没有尝试支持它,我的错误【参考方案11】:

您可以使用print-dict

from print_dict import pd

dict1 = 
    'key': 'value'
 

pd(dict1)

输出:


    'key': 'value'


this Python 代码的输出:


    'one': 'value-one',
    'two': 'value-two',
    'three': 'value-three',
    'four': 
        '1': '1',
        '2': '2',
        '3': [1, 2, 3, 4, 5],
        '4': 
            'method': <function custom_method at 0x7ff6ecd03e18>,
            'tuple': (1, 2),
            'unicode': '✓',
            'ten': 'value-ten',
            'eleven': 'value-eleven',
            '3': [1, 2, 3, 4]
        
    ,
    'object1': <__main__.Object1 object at 0x7ff6ecc588d0>,
    'object2': <Object2 info>,
    'class': <class '__main__.Object1'>


安装:

$ pip install print-dict

披露:我是print-dict的作者

【讨论】:

这是最简单的解决方案。非常适合包含大量嵌套键的大型字典。【参考方案12】:

这里的现代解决方案是使用rich。安装

pip install rich

并用作

from rich import print

d = 
    "Alabama": "Montgomery",
    "Alaska": "Juneau",
    "Arizona": "Phoenix",
    "Arkansas": "Little Rock",
    "California": "Sacramento",
    "Colorado": "Denver",
    "Connecticut": "Hartford",
    "Delaware": "Dover",
    "Florida": "Tallahassee",
    "Georgia": "Atlanta",
    "Hawaii": "Honolulu",
    "Idaho": "Boise",

print(d)

输出很好地缩进:

【讨论】:

用 pprint 和 json.dumps 尝试了一些不同的方法,但没有成功,但效果很好!【参考方案13】:

我采用了sth's answer 并稍微修改了它以适应我对嵌套字典和列表的需求:

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
                                            ...

【讨论】:

【参考方案14】:

我编写了这个简单的代码来打印 Python 中 json 对象的一般结构。

def getstructure(data, tab = 0):
    if type(data) is dict:
        print ' '*tab + '' 
        for key in data:
            print ' '*tab + '  ' + key + ':'
            getstructure(data[key], tab+4)
        print ' '*tab + ''         
    elif type(data) is list and len(data) > 0:
        print ' '*tab + '['
        getstructure(data[0], tab+4)
        print ' '*tab + '  ...'
        print ' '*tab + ']'

以下数据的结果

a = 'list':['a','b',1,2],'dict':'a':1,2:'b','tuple':('a','b',1,2),'function':'p','unicode':u'\xa7',("tuple","key"):"valid"
getstructure(a)

非常紧凑,看起来像这样:


  function:
  tuple:
  list:
    [
      ...
    ]
  dict:
    
      a:
      2:
    
  unicode:
  ('tuple', 'key'):

【讨论】:

【参考方案15】:

我尝试了以下方法并得到了我想要的结果

方法一: 第 1 步:在cmd 中输入以下命令,安装print_dict

pip install print_dict

第 2 步:将 print_dict 导入为

from print_dict import pd

第 3 步:使用pd 打印

pd(your_dictionary_name)

示例输出:


    'Name': 'Arham Rumi',
    'Age': 21,
    'Movies': ['adas', 'adfas', 'fgfg', 'gfgf', 'vbxbv'],
    'Songs': ['sdfsd', 'dfdgfddf', 'dsdfd', 'sddfsd', 'sdfdsdf']

方法二: 我们也可以使用for循环使用items方法打印字典

for key, Value in your_dictionary_name.items():
    print(f"key : Value")

【讨论】:

【参考方案16】:

某事,我下沉了,这很漂亮;)

def pretty(d, indent=0):
    for key, value in d.iteritems():
        if isinstance(value, dict):
            print '\t' * indent + (("%30s: \n") % str(key).upper())
            pretty(value, indent+1)
            print '\t' * indent + ' ' * 32 + (' # end of %s #\n' % str(key).upper())
        elif isinstance(value, list):
            for val in value:
                print '\t' * indent + (("%30s: [\n") % str(key).upper())
                pretty(val, indent+1)
                print '\t' * indent + ' ' * 32 + ('] # end of %s #\n' % str(key).upper())
        else:
            print '\t' * indent + (("%30s: %s") % (str(key).upper(),str(value)))

【讨论】:

-1:不处理不是dict 实例的list 值,即pretty('key': [1, 2, 3], indent=4) ==> AttributeError: 'int' object has no attribute 'iteritems'。我也不喜欢大写键。 您的解决方案认为根字典内的列表内不能有字典。它还认为我们不想打印列表或元组。最后不要大写键,'a':0,'A':1 的结果将不正确。【参考方案17】:
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)

【讨论】:

【参考方案18】:

在接受sth 的回答并做了一个小但非常有用的修改后,我才回到这个问题。此函数打印所有 JSON 树中的键 以及该树中的叶节点的大小

def print_JSON_tree(d, indent=0):
    for key, value in d.iteritems():
        print '    ' * indent + unicode(key),
        if isinstance(value, dict):
            print; print_JSON_tree(value, indent+1)
        else:
            print ":", str(type(d[key])).split("'")[1], "-", str(len(unicode(d[key])))

当您拥有大型 JSON 对象并想弄清楚肉在哪里时,这真的很棒。 示例

>>> print_JSON_tree(JSON_object)
key1
    value1 : int - 5
    value2 : str - 16
    key2
       value1 : str - 34
       value2 : list - 5623456

这会告诉您,您关心的大部分数据可能都在 JSON_object['key1']['key2']['value2'] 中,因为格式化为字符串的值的长度非常大。

【讨论】:

【参考方案19】:

我使用了你们教给我的东西以及装饰器的力量来重载经典的打印功能。只需根据您的需要更改缩进即可。我在 github 中将其添加为 gist,以防您想加注星标(保存)。

def print_decorator(func):
    """
    Overload Print function to pretty print Dictionaries 
    """
    def wrapped_func(*args,**kwargs):
        if isinstance(*args, dict):
            return func(json.dumps(*args, sort_keys=True, indent=2, default=str))
        else:
            return func(*args,**kwargs)
    return wrapped_func
print = print_decorator(print)

现在像往常一样使用 print。

【讨论】:

注意:仅在 Python 3 中有效,因为在 Python 2 中,print 是一个关键字,因此无法赋值。【参考方案20】:

我自己是一个相对的 python 新手,但过去几周我一直在使用嵌套字典,这就是我想出的。

您应该尝试使用堆栈。将根字典中的键变成列表的列表:

stack = [ root.keys() ]     # Result: [ [root keys] ]

按倒序从最后到第一个,查找字典中的每个键以查看其值是否(也)是字典。如果没有,请打印密钥然后将其删除。但是,如果键 的值是一个字典,则打印该键,然后将该值的键附加到堆栈的末尾,并以相同的方式开始处理该列表,为每个新的递归重复键列表。

如果每个列表中第二个键的值是一个字典,那么在几轮之后你会得到这样的结果:

[['key 1','key 2'],['key 2.1','key 2.2'],['key 2.2.1','key 2.2.2'],[`etc.`]]

这种方法的好处是缩进只是\t 乘以堆栈长度:

indent = "\t" * len(stack)

缺点是,为了检查每个键,您需要散列到相关的子字典,尽管这可以通过列表理解和简单的 for 循环轻松处理:

path = [li[-1] for li in stack]
# The last key of every list of keys in the stack

sub = root
for p in path:
    sub = sub[p]


if type(sub) == dict:
    stack.append(sub.keys()) # And so on

请注意,这种方法将要求您清理尾随的空列表,删除任何列表中的最后一个键,然后是一个空列表(这当然可能会创建另一个空列表,等等开)。

还有其他方法可以实现这种方法,但希望这能让您对如何实现它有一个基本的了解。

编辑:如果您不想经历所有这些,pprint 模块会以很好的格式打印嵌套字典。

【讨论】:

【参考方案21】:

这是我根据某事的评论编写的一个函数。它的工作原理与带有缩进的 json.dumps 相同,但我使用制表符而不是空格来缩进。在 Python 3.2+ 中,您可以直接将缩进指定为 '\t',但在 2.7 中则不行。

def pretty_dict(d):
    def pretty(d, indent):
        for i, (key, value) in enumerate(d.iteritems()):
            if isinstance(value, dict):
                print '0"1": '.format( '\t' * indent, str(key))
                pretty(value, indent+1)
                if i == len(d)-1:
                    print '0'.format( '\t' * indent)
                else:
                    print '0,'.format( '\t' * indent)
            else:
                if i == len(d)-1:
                    print '0"1": "2"'.format( '\t' * indent, str(key), value)
                else:
                    print '0"1": "2",'.format( '\t' * indent, str(key), value)
    print ''
    pretty(d,indent=1)
    print ''

例如:

>>> dict_var = 'a':2, 'b':'x':3, 'y':'t1': 4, 't2':5
>>> pretty_dict(dict_var)

    "a": "2",
    "b": 
        "y": 
            "t2": "5",
            "t1": "4"
        ,
        "x": "3"
    

【讨论】:

我无法让它与我的解决方案的嵌套字典一起使用,因为它给了我一个 UnicodeEncodeError,项目和键也都转换为字符串,如果我们使用包含列表的数字或元组怎么办和听写?最后,您的解决方案考虑到我们想要漂亮打印的对象必须是字典。 我并没有尝试为 python dict 编写通用打印函数。评价最高的 cmets 已经演示了如何漂亮地打印字典。我的贡献是使用 '\t' 编写 json.dumps 的替代方案,用于缩进而不是 python 2.7 中的制表符。 我同意你写一个 json.dumps 的替代方案,对我来说,与 json.dumps 相同的问题也适用。此外,您可以使用简单的正则表达式来更改缩进类型,从而使您的代码更简单。【参考方案22】:

这里有一些东西可以打印任何类型的嵌套字典,同时跟踪“父”字典。

dicList = list()

def prettierPrint(dic, dicList):
count = 0
for key, value in dic.iteritems():
    count+=1
    if str(value) == 'OrderedDict()':
        value = None
    if not isinstance(value, dict):
        print str(key) + ": " + str(value)
        print str(key) + ' was found in the following path:',
        print dicList
        print '\n'
    elif isinstance(value, dict):
        dicList.append(key)
        prettierPrint(value, dicList)
    if dicList:
         if count == len(dic):
             dicList.pop()
             count = 0

prettierPrint(dicExample, dicList)

这是根据不同格式打印的良好起点,例如 OP 中指定的格式。您真正需要做的就是围绕 Print 块进行操作。请注意,它会查看值是否为“OrderedDict()”。根据您是否使用来自Container datatypes Collections 的内容,您应该进行此类故障保护,以便 elif 块不会因为其名称而将其视为附加字典。截至目前,像

这样的示例字典
example_dict = 'key1': 'value1',
            'key2': 'value2',
            'key3': 'key3a': 'value3a',
            'key4': 'key4a': 'key4aa': 'value4aa',
                               'key4ab': 'value4ab',
                               'key4ac': 'value4ac',
                     'key4b': 'value4b'

将打印

key3a: value3a
key3a was found in the following path: ['key3']

key2: value2
key2 was found in the following path: []

key1: value1
key1 was found in the following path: []

key4ab: value4ab
key4ab was found in the following path: ['key4', 'key4a']

key4ac: value4ac
key4ac was found in the following path: ['key4', 'key4a']

key4aa: value4aa
key4aa was found in the following path: ['key4', 'key4a']

key4b: value4b
key4b was found in the following path: ['key4']

~修改代码以适应问题的格式~

lastDict = list()
dicList = list()
def prettierPrint(dic, dicList):
    global lastDict
    count = 0
    for key, value in dic.iteritems():
        count+=1
        if str(value) == 'OrderedDict()':
            value = None
        if not isinstance(value, dict):
            if lastDict == dicList:
                sameParents = True
            else:
                sameParents = False

            if dicList and sameParents is not True:
                spacing = ' ' * len(str(dicList))
                print dicList
                print spacing,
                print str(value)

            if dicList and sameParents is True:
                print spacing,
                print str(value)
            lastDict = list(dicList)

        elif isinstance(value, dict):
            dicList.append(key)
            prettierPrint(value, dicList)

        if dicList:
             if count == len(dic):
                 dicList.pop()
                 count = 0

使用相同的示例代码,它将打印以下内容:

['key3']
         value3a
['key4', 'key4a']
                  value4ab
                  value4ac
                  value4aa
['key4']
         value4b

这不是完全在 OP 中要求的。不同之处在于仍会打印 parent^n,而不是不存在并替换为空白。要获得 OP 的格式,您需要执行以下操作:迭代地将 dicListlastDict 进行比较。您可以通过创建一个新字典并将 dicList 的内容复制到其中来执行此操作,检查复制字典中的 i 是否与 lastDict 中的 i 相同,并且 -- 如果它is -- 使用字符串乘法器函数将空格写入该 i 位置。

【讨论】:

【参考方案23】:

来自this link:

def prnDict(aDict, br='\n', html=0,
            keyAlign='l',   sortKey=0,
            keyPrefix='',   keySuffix='',
            valuePrefix='', valueSuffix='',
            leftMargin=0,   indent=1 ):
    '''
return a string representive of aDict in the following format:
    
     key1: value1,
     key2: value2,
     ...
     

Spaces will be added to the keys to make them have same width.

sortKey: set to 1 if want keys sorted;
keyAlign: either 'l' or 'r', for left, right align, respectively.
keyPrefix, keySuffix, valuePrefix, valueSuffix: The prefix and
   suffix to wrap the keys or values. Good for formatting them
   for html document(for example, keyPrefix='<b>', keySuffix='</b>'). 
   Note: The keys will be padded with spaces to have them
         equally-wide. The pre- and suffix will be added OUTSIDE
         the entire width.
html: if set to 1, all spaces will be replaced with '&nbsp;', and
      the entire output will be wrapped with '<code>' and '</code>'.
br: determine the carriage return. If html, it is suggested to set
    br to '<br>'. If you want the html source code eazy to read,
    set br to '<br>\n'

version: 04b52
author : Runsun Pan
require: odict() # an ordered dict, if you want the keys sorted.
         Dave Benjamin 
         http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/161403
    '''

    if aDict:

        #------------------------------ sort key
        if sortKey:
            dic = aDict.copy()
            keys = dic.keys()
            keys.sort()
            aDict = odict()
            for k in keys:
                aDict[k] = dic[k]

        #------------------- wrap keys with ' ' (quotes) if str
        tmp = ['']
        ks = [type(x)==str and "'%s'"%x or x for x in aDict.keys()]

        #------------------- wrap values with ' ' (quotes) if str
        vs = [type(x)==str and "'%s'"%x or x for x in aDict.values()] 

        maxKeyLen = max([len(str(x)) for x in ks])

        for i in range(len(ks)):

            #-------------------------- Adjust key width
            k = 1            : str(ks[i]).ljust(maxKeyLen),
                 keyAlign=='r': str(ks[i]).rjust(maxKeyLen) [1]

            v = vs[i]        
            tmp.append(' '* indent+ '%s%s%s:%s%s%s,' %(
                        keyPrefix, k, keySuffix,
                        valuePrefix,v,valueSuffix))

        tmp[-1] = tmp[-1][:-1] # remove the ',' in the last item
        tmp.append('')

        if leftMargin:
          tmp = [ ' '*leftMargin + x for x in tmp ]

        if html:
            return '<code>%s</code>' %br.join(tmp).replace(' ','&nbsp;')
        else:
            return br.join(tmp)     
    else:
        return ''

'''
Example:

>>> a='C': 2, 'B': 1, 'E': 4, (3, 5): 0

>>> print prnDict(a)

 'C'   :2,
 'B'   :1,
 'E'   :4,
 (3, 5):0


>>> print prnDict(a, sortKey=1)

 'B'   :1,
 'C'   :2,
 'E'   :4,
 (3, 5):0


>>> print prnDict(a, keyPrefix="<b>", keySuffix="</b>")

 <b>'C'   </b>:2,
 <b>'B'   </b>:1,
 <b>'E'   </b>:4,
 <b>(3, 5)</b>:0


>>> print prnDict(a, html=1)
<code>
&nbsp;'C'&nbsp;&nbsp;&nbsp;:2,
&nbsp;'B'&nbsp;&nbsp;&nbsp;:1,
&nbsp;'E'&nbsp;&nbsp;&nbsp;:4,
&nbsp;(3,&nbsp;5):0
</code>

>>> b='car': [6, 6, 12], 'about': [15, 9, 6], 'bookKeeper': [9, 9, 15]

>>> print prnDict(b, sortKey=1)

 'about'     :[15, 9, 6],
 'bookKeeper':[9, 9, 15],
 'car'       :[6, 6, 12]


>>> print prnDict(b, keyAlign="r")

        'car':[6, 6, 12],
      'about':[15, 9, 6],
 'bookKeeper':[9, 9, 15]

'''

【讨论】:

【参考方案24】:

使用此功能:

def pretty_dict(d, n=1):
    for k in d:
        print(" "*n + k)
        try:
            pretty_dict(d[k], n=n+4)
        except TypeError:
            continue

这样称呼它:

pretty_dict(mydict)

【讨论】:

如果值是字符串,这不起作用。它在新行上打印字符串的每个字符,但键似乎可以正常工作。【参考方案25】:

这是我在处理需要在 .txt 文件中编写字典的类时想到的:

@staticmethod
def _pretty_write_dict(dictionary):

    def _nested(obj, level=1):
        indentation_values = "\t" * level
        indentation_braces = "\t" * (level - 1)
        if isinstance(obj, dict):
            return "\n%(body)s%(indent_braces)s" % 
                "body": "".join("%(indent_values)s\'%(key)s\': %(value)s,\n" % 
                    "key": str(key),
                    "value": _nested(value, level + 1),
                    "indent_values": indentation_values
                 for key, value in obj.items()),
                "indent_braces": indentation_braces
            
        if isinstance(obj, list):
            return "[\n%(body)s\n%(indent_braces)s]" % 
                "body": "".join("%(indent_values)s%(value)s,\n" % 
                    "value": _nested(value, level + 1),
                    "indent_values": indentation_values
                 for value in obj),
                "indent_braces": indentation_braces
            
        else:
            return "\'%(value)s\'" % "value": str(obj)

    dict_text = _nested(dictionary)
    return dict_text

现在,如果我们有这样的字典:

some_dict = 'default': 'ENGINE': [1, 2, 3, 'some_key': 'some_other_key': 'some_value'], 'NAME': 'some_db_name', 'PORT': '', 'HOST': 'localhost', 'USER': 'some_user_name', 'PASSWORD': 'some_password', 'OPTIONS': 'init_command': 'SET foreign_key_checks = 0;'

我们做到了:

print(_pretty_write_dict(some_dict))

我们得到:


    'default': 
        'ENGINE': [
            '1',
            '2',
            '3',
            
                'some_key': 
                    'some_other_key': 'some_value',
                ,
            ,
        ],
        'NAME': 'some_db_name',
        'OPTIONS': 
            'init_command': 'SET foreign_key_checks = 0;',
        ,
        'HOST': 'localhost',
        'USER': 'some_user_name',
        'PASSWORD': 'some_password',
        'PORT': '',
    ,

【讨论】:

以上是关于如何漂亮地打印嵌套字典?的主要内容,如果未能解决你的问题,请参考以下文章

如何使用 Go 漂亮地打印 JSON?

如何美观地打印 Python 对象?

python:漂亮打印深层嵌套字符串(mastermind游戏)

Python:Jupyter Notebook 中的漂亮打印

如何使用缩进将 HTML 漂亮地打印到文件中

如何漂亮地打印 Golang 结构? [复制]