如何漂亮的打印嵌套字典?
我怎么能在Python中打印深度为〜4的字典呢? 我尝试使用pprint()
漂亮的打印,但是不起作用:
import pprint pp = pprint.PrettyPrinter(indent=4) pp.pprint(mydict)
我只是想每个嵌套的缩进( "\t"
),所以我得到这样的东西:
key1 value1 value2 key2 value1 value2
等等
我该怎么做?
我不确定你想要的格式如何,但你可以从这样的function开始:
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))
( 对于Python 2用户:从__future__导入打印function )
我的第一个想法是,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 } } }
至于做了什么,我没有看到任何漂亮的打印机,至less模仿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()
它可以支持为已定义的types添加格式化程序,您只需要为此types创build一个函数,然后使用set_formater将其绑定到所需的types:
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)
由于历史的原因,我保留了前一个漂亮的打印机,它是一个function而不是一个类,但是它们都可以用同样的方式使用,而类的版本只允许更多的:
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' }
与其他版本相比:
- 这个解决scheme直接查找对象types,所以你可以打印几乎所有的东西,不仅仅是列表或者字典。
- 没有任何依赖性。
- 一切都放在一个string中,所以你可以随心所欲地做任何事情。
- 该类和函数已经过testing,并与Python 2.7和3.4一起工作。
- 你可以有所有types的对象里面,这是他们的表示,而不是他们的内容放在结果(所以string有引号,Unicodestring充分表示…)。
- 使用类版本,您可以添加所需的每种对象types的格式或将其更改为已定义的types。
- 键可以是任何有效的types。
- 缩进和换行符可以改变我们想要的一切。
- 字典,列表和元组相当印刷。
你可以通过PyYAML试试YAML 。 它的输出可以被微调。 我build议从以下开始:
print yaml.dump(data, allow_unicode=True, default_flow_style=False)
结果是非常可读的; 如果需要,也可以将其parsing回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
我拿出了答案 ,并稍微修改它,以适应我的嵌套字典和列表的需要:
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 ...
和其他人一样,可以使用recursion / dfs打印嵌套的字典数据,如果是字典,则recursion调用; 否则打印数据。
>>> def print_json(data): ... if type(data) == dict: ... for k,v in data.items(): ... print k ... print_json(v) ... else: ... print data ...
嗯,我沉迷于此;)
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)))
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)
我写了这个简单的代码来打印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'): }
这里有一些可以打印任何嵌套的字典,同时跟踪“父”字典。
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中指定的格式。 你真正需要做的是围绕打印块的操作。 请注意,它看起来是否值为'OrderedDict()'。 根据是否使用Container数据types集合中的某些内容,您应该创build这些types的故障保险箱,以便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所要求的。 不同的是,父母^仍然是打印,而不是缺席,取而代之的是空白。 要得到OP的格式,你需要做如下的事情:迭代比较dicList和lastDict 。 你可以通过创build一个新的字典并将dicList的内容复制到它来检查复制的字典中的i是否与lastDict中的i是相同的,如果是 – 使用string乘数函数将空格写入该位置。
从这个链接 :
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 ' ', 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(' ',' ') 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>{ 'C' :2, 'B' :1, 'E' :4, (3, 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] } '''
我只是回答这个问题后,作出了一个小的,但非常有用的修改。 该函数打印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']
因为格式化为string的值的长度非常大。
我自己是一个相对的Python新手,但是过去几周我一直在使用嵌套字典,而这正是我所想到的。
你应该尝试使用堆栈。 将根字典中的键转换为列表的列表:
stack = [ root.keys() ] # Result: [ [root keys] ]
按照从上到下的相反顺序,查找字典中的每个键以查看它的值是否也是字典。 如果没有,则打印该密钥然后删除它。 但是,如果键的值是字典,则打印该键,然后将该值的键追加到堆栈的末尾,然后以相同的方式开始处理该列表,对每个新的键列表recursion地重复。
如果每个列表中的第二个键的值是一个字典,你会在几轮之后得到这样的结果:
[['key 1','key 2'],['key 2.1','key 2.2'],['key 2.2.1','key 2.2.2'],[`etc.`]]
这种方法的好处是缩进只是堆栈长度的两倍。
indent = "\t" * len(stack)
不足之处在于,为了检查每个关键字,需要对相关的子字典进行散列,尽pipe这可以通过列表理解和简单的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
请注意,这种方法将要求您清理尾随的空列表, 并删除任何列表中的最后一个键,然后是空列表(这当然可能会创build另一个空列表,等等)。
还有其他的方法来实现这种方法,但希望这给你一个基本的想法,如何做到这一点。
编辑:如果你不想通过所有的, pprint
模块打印嵌套字典在一个不错的格式。
这是我根据什么评论写的function。 它的作品与缩进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" } }