有没有什么方法可以正确地打印有序的词典?

Eli*_*ria 91 python pretty-print ordereddictionary python-2.7 pprint

我喜欢Python中的pprint模块.我经常使用它进行测试和调试.我经常使用width选项来确保输出在我的终端窗口中很好地适应.

它一直运行良好,直到他们在Python 2.7中添加了新的有序字典类型(我非常喜欢的另一个很酷的功能).如果我试着漂亮地打印一个有序的字典,它就不能很好地显示出来.而不是将每个键值对放在它自己的行上,整个事物显示在一条长行上,它包含很多次并且难以阅读.

这里有没有人有办法让它打印得很好,就像旧的无序词典一样?如果我花了足够的时间,我可能会想出一些东西,可能使用PrettyPrinter.format方法,但我想知道这里是否有人知道解决方案.

更新:我为此提交了一份错误报告.您可以在http://bugs.python.org/issue10592上看到它.

web*_*rst 124

作为临时解决方法,您可以尝试以JSON格式转储.你丢失了一些类型的信息,但它看起来不错,并保持秩序.

import json

pprint(data, indent=4)
# ^ugly

print(json.dumps(data, indent=4))
# ^nice
Run Code Online (Sandbox Code Playgroud)

  • @scottmrogowski为什么不简单地``pprint.pprint(dict(data))`? (7认同)
  • @Alfe如果dict嵌套了OrderedDicts,它们将无法很好地显示 (7认同)
  • 如果你不关心键的顺序,`pprint.pprint(dict(data))`效果很好.就个人而言,我希望`OrchedDict`的`__repr__`会产生这样的输出但保留键的顺序. (2认同)
  • @Alfe:因为这样,输出没有顺序。首先使用OrderedDict而不是dict的原因是因为顺序很重要。 (2认同)

kzh*_*kzh 15

如果您的OrderedDict的顺序是alpha排序,则以下内容将起作用,因为pprint将在打印前对dict进行排序.

pprint(dict(o.items()))
Run Code Online (Sandbox Code Playgroud)

  • 由于OrderedDicts按插入顺序排序,因此这可能适用于一小部分用途.无论如何,将OD转换为"dict"应该避免将所有内容放在一行上的问题. (2认同)

mar*_*eau 8

这是另一个通过在pprint()内部覆盖和使用stock 函数的方法.与我之前的那个不同,它将处理OrderedDict另一个容器(例如a),list并且还应该能够处理给定的任何可选关键字参数 - 但是它对另一个容器提供的输出没有相同程度的控制.

它通过将stock函数的输出重定向到临时缓冲区,然后在将其发送到输出流之前将其换行来进行操作.虽然产生的最终输出并不是特别漂亮,但它很不错并且可能"足够好"用作解决方法.

更新2.0

通过使用标准库textwrap模块简化,并修改为在Python 2和3中都可以使用.

from collections import OrderedDict
try:
    from cStringIO import StringIO
except ImportError:  # Python 3
    from io import StringIO
from pprint import pprint as pp_pprint
import sys
import textwrap

def pprint(object, **kwrds):
    try:
        width = kwrds['width']
    except KeyError: # unlimited, use stock function
        pp_pprint(object, **kwrds)
        return
    buffer = StringIO()
    stream = kwrds.get('stream', sys.stdout)
    kwrds.update({'stream': buffer})
    pp_pprint(object, **kwrds)
    words = buffer.getvalue().split()
    buffer.close()

    # word wrap output onto multiple lines <= width characters
    try:
        print >> stream, textwrap.fill(' '.join(words), width=width)
    except TypeError:  # Python 3
        print(textwrap.fill(' '.join(words), width=width), file=stream)

d = dict((('john',1), ('paul',2), ('mary',3)))
od = OrderedDict((('john',1), ('paul',2), ('mary',3)))
lod = [OrderedDict((('john',1), ('paul',2), ('mary',3))),
       OrderedDict((('moe',1), ('curly',2), ('larry',3))),
       OrderedDict((('weapons',1), ('mass',2), ('destruction',3)))]
Run Code Online (Sandbox Code Playgroud)

样本输出:

pprint(d, width=40)
Run Code Online (Sandbox Code Playgroud)

»   {'john': 1, 'mary': 3, 'paul': 2}

pprint(od, width=40)
Run Code Online (Sandbox Code Playgroud)

» OrderedDict([('john', 1), ('paul', 2),
   ('mary', 3)])

pprint(lod, width=40)
Run Code Online (Sandbox Code Playgroud)

» [OrderedDict([('john', 1), ('paul', 2),
   ('mary', 3)]), OrderedDict([('moe', 1),
   ('curly', 2), ('larry', 3)]),
   OrderedDict([('weapons', 1), ('mass',
   2), ('destruction', 3)])]


Ily*_*kin 7

要打印有序的字典,例如

from collections import OrderedDict

d=OrderedDict([
    ('a', OrderedDict([
        ('a1',1),
        ('a2','sss')
    ])),
    ('b', OrderedDict([
        ('b1', OrderedDict([
            ('bb1',1),
            ('bb2',4.5)])),
        ('b2',4.5)
    ])),
])
Run Code Online (Sandbox Code Playgroud)

我做

def dict_or_OrdDict_to_formatted_str(OD, mode='dict', s="", indent=' '*4, level=0):
    def is_number(s):
        try:
            float(s)
            return True
        except ValueError:
            return False
    def fstr(s):
        return s if is_number(s) else '"%s"'%s
    if mode != 'dict':
        kv_tpl = '("%s", %s)'
        ST = 'OrderedDict([\n'; END = '])'
    else:
        kv_tpl = '"%s": %s'
        ST = '{\n'; END = '}'
    for i,k in enumerate(OD.keys()):
        if type(OD[k]) in [dict, OrderedDict]:
            level += 1
            s += (level-1)*indent+kv_tpl%(k,ST+dict_or_OrdDict_to_formatted_str(OD[k], mode=mode, indent=indent, level=level)+(level-1)*indent+END)
            level -= 1
        else:
            s += level*indent+kv_tpl%(k,fstr(OD[k]))
        if i!=len(OD)-1:
            s += ","
        s += "\n"
    return s

print dict_or_OrdDict_to_formatted_str(d)
Run Code Online (Sandbox Code Playgroud)

哪个收益率

"a": {
    "a1": 1,
    "a2": "sss"
},
"b": {
    "b1": {
        "bb1": 1,
        "bb2": 4.5
    },
    "b2": 4.5
}
Run Code Online (Sandbox Code Playgroud)

要么

print dict_or_OrdDict_to_formatted_str(d, mode='OD')
Run Code Online (Sandbox Code Playgroud)

产量

("a", OrderedDict([
    ("a1", 1),
    ("a2", "sss")
])),
("b", OrderedDict([
    ("b1", OrderedDict([
        ("bb1", 1),
        ("bb2", 4.5)
    ])),
    ("b2", 4.5)
]))
Run Code Online (Sandbox Code Playgroud)


rum*_*pel 5

这是一种破解实施的方式pprint. pprint在打印之前对键进行排序,因此为了保持顺序,我们只需要按照我们想要的方式对键进行排序.

请注意,这会影响items()功能.因此,您可能希望在执行pprint后保留和恢复被覆盖的函数.

from collections import OrderedDict
import pprint

class ItemKey(object):
  def __init__(self, name, position):
    self.name = name
    self.position = position
  def __cmp__(self, b):
    assert isinstance(b, ItemKey)
    return cmp(self.position, b.position)
  def __repr__(self):
    return repr(self.name)

OrderedDict.items = lambda self: [
    (ItemKey(name, i), value)
    for i, (name, value) in enumerate(self.iteritems())]
OrderedDict.__repr__ = dict.__repr__

a = OrderedDict()
a[4] = '4'
a[1] = '1'
a[2] = '2'
print pprint.pformat(a) # {4: '4', 1: '1', 2: '2'}
Run Code Online (Sandbox Code Playgroud)

  • 很好,但更好的子类型然后覆盖功能. (2认同)

Jak*_*yer 2

def pprint_od(od):
    print "{"
    for key in od:
        print "%s:%s,\n" % (key, od[key]) # Fixed syntax
    print "}"
Run Code Online (Sandbox Code Playgroud)

就这样吧^^

for item in li:
    pprint_od(item)
Run Code Online (Sandbox Code Playgroud)

或者

(pprint_od(item) for item in li)
Run Code Online (Sandbox Code Playgroud)