Python 有什么方法可以正确打印有序字典?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/4301069/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Any way to properly pretty-print ordered dictionaries?
提问by Elias Zamaria
I like the pprint module in Python. I use it a lot for testing and debugging. I frequently use the width option to make sure the output fits nicely within my terminal window.
我喜欢 Python 中的 pprint 模块。我经常使用它进行测试和调试。我经常使用宽度选项来确保输出非常适合我的终端窗口。
It has worked fine until they added the new ordered dictionary typein Python 2.7 (another cool feature I really like). If I try to pretty-print an ordered dictionary, it doesn't show nicely. Instead of having each key-value pair on its own line, the whole thing shows up on one long line, which wraps many times and is hard to read.
它一直运行良好,直到他们在 Python 2.7 中添加了新的有序字典类型(我非常喜欢的另一个很酷的功能)。如果我尝试漂亮地打印一个有序的字典,它不会很好地显示。不是将每个键值对都放在自己的一行上,而是将整个内容显示在一个长行中,该行包含很多次并且难以阅读。
Does anyone here have a way to make it print nicely, like the old unordered dictionaries? I could probably figure something out, possibly using the PrettyPrinter.format method, if I spend enough time, but I am wondering if anyone here already knows of a solution.
这里有没有人有办法让它打印得很好,就像旧的无序词典一样?如果我花足够的时间,我可能会想出一些办法,可能使用 PrettyPrinter.format 方法,但我想知道这里是否有人已经知道解决方案。
UPDATE:I filed a bug report for this. You can see it at http://bugs.python.org/issue10592.
更新:我为此提交了错误报告。你可以在http://bugs.python.org/issue10592看到它。
回答by Jakob Bowyer
def pprint_od(od):
print "{"
for key in od:
print "%s:%s,\n" % (key, od[key]) # Fixed syntax
print "}"
There you go ^^
给你^^
for item in li:
pprint_od(item)
or
或者
(pprint_od(item) for item in li)
回答by kzh
The following will work if the order of your OrderedDict is an alpha sort, since pprint will sort a dict before print.
如果 OrderedDict 的顺序是 alpha 排序,以下将起作用,因为 pprint 将在打印之前对 dict 进行排序。
pprint(dict(o.items()))
回答by martineau
You could redefine pprint()and intercept calls for OrderedDict's. Here's a simple illustration. As written, the OrderedDictoverride code ignores any optional stream, indent, width, or depthkeywords that may have been passed, but could be enhanced to implement them. Unfortunately this technique doesn't handle them inside another container, such as a listof OrderDict's
您可以重新定义pprint()和拦截对OrderedDict's 的调用。这是一个简单的说明。正如所写的那样,OrderedDict覆盖代码会忽略可能已传递但可以增强以实现它们的任何可选的stream、indent、width或depth关键字。不幸的是,这种技术不能在另一个容器中处理它们,例如 a listofOrderDict的
from collections import OrderedDict
from pprint import pprint as pp_pprint
def pprint(obj, *args, **kwrds):
if not isinstance(obj, OrderedDict):
# use stock function
return pp_pprint(obj, *args, **kwrds)
else:
# very simple sample custom implementation...
print "{"
for key in obj:
print " %r:%r" % (key, obj[key])
print "}"
l = [10, 2, 4]
d = dict((('john',1), ('paul',2), ('mary',3)))
od = OrderedDict((('john',1), ('paul',2), ('mary',3)))
pprint(l, width=4)
# [10,
# 2,
# 4]
pprint(d)
# {'john': 1, 'mary': 3, 'paul': 2}
pprint(od)
# {
# 'john':1
# 'paul':2
# 'mary':3
# }
回答by martineau
Here's another answer that works by overriding and using the stock pprint()function internally. Unlike my earlier oneit willhandle OrderedDict's inside another container such as a listand should also be able to handle any optional keyword arguments given — however it does not have the same degree of control over the output that the other one afforded.
这是另一个通过在pprint()内部覆盖和使用 stock函数来工作的答案。与我之前的不同,它会OrderedDict在另一个容器(例如 a)中处理's ,list并且还应该能够处理给定的任何可选关键字参数——但是它对输出的控制程度与另一个容器不同。
It operates by redirecting the stock function's output into a temporary buffer and then word wraps that before sending it on to the output stream. While the final output produced isn't exceptionalily pretty, it's decent and may be "good enough" to use as a workaround.
它通过将股票函数的输出重定向到临时缓冲区,然后在将其发送到输出流之前对其进行自动换行。虽然产生的最终输出不是特别漂亮,但它很不错,可能“足够好”用作解决方法。
Update 2.0
更新 2.0
Simplified by using standard library textwrapmodule, and modified to work in
both Python 2 & 3.
通过使用标准库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)))]
Sample output:
示例输出:
pprint(d, width=40)
? {'john': 1, 'mary': 3, 'paul': 2}
? {'john': 1, 'mary': 3, 'paul': 2}
pprint(od, width=40)
? OrderedDict([('john', 1), ('paul', 2),
('mary', 3)])
? OrderedDict([('john', 1), ('paul', 2),
('mary', 3)])
pprint(lod, width=40)
? [OrderedDict([('john', 1), ('paul', 2),
('mary', 3)]), OrderedDict([('moe', 1),
('curly', 2), ('larry', 3)]),
OrderedDict([('weapons', 1), ('mass',
2), ('destruction', 3)])]
? [OrderedDict([('john', 1), ('paul', 2),
('mary', 3)]), OrderedDict([('moe', 1),
('curly', 2), ('larry', 3)]),
OrderedDict([('weapons', 1), ('mass',
2), ('destruction', 3)])]
回答by webwurst
As a temporary workaround you can try dumping in JSON format. You lose some type information, but it looks nice and keeps the order.
作为临时解决方法,您可以尝试以 JSON 格式转储。您丢失了一些类型信息,但它看起来不错并且保持了顺序。
import json
pprint(data, indent=4)
# ^ugly
print(json.dumps(data, indent=4))
# ^nice
回答by Bill M.
The pprint()method is just invoking the __repr__()method of things in it, and OrderedDictdoesn't appear to do much in it's method (or doesn't have one or something).
该pprint()方法只是调用其中__repr__()的事物的方法,并且OrderedDict在它的方法中似乎没有做太多事情(或者没有一个或什么)。
Here's a cheap solution that should work IF YOU DON'T CARE ABOUT THE ORDER BEING VISIBLE IN THE PPRINT OUTPUT, which may be a big if:
这是一个廉价的解决方案,如果您不关心在 PPRINT 输出中可见的订单,它应该可以工作,如果:
class PrintableOrderedDict(OrderedDict):
def __repr__(self):
return dict.__repr__(self)
I'm actually surprised that the order isn't preserved... ah well.
我实际上很惊讶订单没有保留......嗯。
回答by LondonRob
If the dictionary items are all of one type, you could use the amazing data-handling library pandas:
如果字典项都是一种类型,您可以使用惊人的数据处理库pandas:
>>> import pandas as pd
>>> x = {'foo':1, 'bar':2}
>>> pd.Series(x)
bar 2
foo 1
dtype: int64
or
或者
>>> import pandas as pd
>>> x = {'foo':'bar', 'baz':'bam'}
>>> pd.Series(x)
baz bam
foo bar
dtype: object
回答by flutefreak7
This is pretty crude, but I just needed a way to visualize a data structure made up of any arbitrary Mappings and Iterables and this is what I came up with before giving up. It's recursive, so it will fall through nested structures and lists just fine. I used the Mapping and Iterable abstract base classes from collections to handle just about anything.
这很粗糙,但我只需要一种方法来可视化由任意映射和迭代组成的数据结构,这就是我在放弃之前想到的。它是递归的,所以它会很好地通过嵌套结构和列表。我使用集合中的 Mapping 和 Iterable 抽象基类来处理几乎任何事情。
I was aiming for almost yaml like output with concise python code, but didn't quite make it.
我的目标是使用简洁的 python 代码获得几乎 yaml 的输出,但并没有完全实现。
def format_structure(d, level=0):
x = ""
if isinstance(d, Mapping):
lenk = max(map(lambda x: len(str(x)), d.keys()))
for k, v in d.items():
key_text = "\n" + " "*level + " "*(lenk - len(str(k))) + str(k)
x += key_text + ": " + format_structure(v, level=level+lenk)
elif isinstance(d, Iterable) and not isinstance(d, basestring):
for e in d:
x += "\n" + " "*level + "- " + format_structure(e, level=level+4)
else:
x = str(d)
return x
and some test data using OrderedDict and lists of OrderedDicts... (sheesh Python needs OrderedDict literals sooo badly...)
和一些使用 OrderedDict 和 OrderedDicts 列表的测试数据......(sheesh Python 非常需要 OrderedDict 文字......)
d = OrderedDict([("main",
OrderedDict([("window",
OrderedDict([("size", [500, 500]),
("position", [100, 900])])),
("splash_enabled", True),
("theme", "Dark")])),
("updates",
OrderedDict([("automatic", True),
("servers",
[OrderedDict([("url", "http://server1.com"),
("name", "Stable")]),
OrderedDict([("url", "http://server2.com"),
("name", "Beta")]),
OrderedDict([("url", "http://server3.com"),
("name", "Dev")])]),
("prompt_restart", True)])),
("logging",
OrderedDict([("enabled", True),
("rotate", True)]))])
print format_structure(d)
yields the following output:
产生以下输出:
main:
window:
size:
- 500
- 500
position:
- 100
- 900
splash_enabled: True
theme: Dark
updates:
automatic: True
servers:
-
url: http://server1.com
name: Stable
-
url: http://server2.com
name: Beta
-
url: http://server3.com
name: Dev
prompt_restart: True
logging:
enabled: True
rotate: True
I had some thoughts along the way of using str.format() for better alignment, but didn't feel like digging into it. You'd need to dynamically specify the field widths depending on the type of alignment you want, which would get either tricky or cumbersome.
我对使用 str.format() 进行更好的对齐有一些想法,但不想深入研究。您需要根据所需的对齐类型动态指定字段宽度,这会变得棘手或繁琐。
Anyway, this shows me my data in readable hierarchical fashion, so that works for me!
无论如何,这以可读的分层方式向我展示了我的数据,所以这对我有用!
回答by Ilya Prokin
To print an ordered dict, e.g.
打印一个有序的字典,例如
from collections import OrderedDict
d=OrderedDict([
('a', OrderedDict([
('a1',1),
('a2','sss')
])),
('b', OrderedDict([
('b1', OrderedDict([
('bb1',1),
('bb2',4.5)])),
('b2',4.5)
])),
])
I do
我愿意
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)
Which yields
哪个产量
"a": {
"a1": 1,
"a2": "sss"
},
"b": {
"b1": {
"bb1": 1,
"bb2": 4.5
},
"b2": 4.5
}
or
或者
print dict_or_OrdDict_to_formatted_str(d, mode='OD')
which yields
这产生
("a", OrderedDict([
("a1", 1),
("a2", "sss")
])),
("b", OrderedDict([
("b1", OrderedDict([
("bb1", 1),
("bb2", 4.5)
])),
("b2", 4.5)
]))
回答by rumpel
Here's a way that hacks the implementation of pprint.
pprintsorts the keys before printing, so to preserve order, we just have to make the keys sort in the way we want.
这是一种破解pprint.
pprint在打印之前对键进行排序,因此为了保持顺序,我们只需要按照我们想要的方式对键进行排序。
Note that this impacts the items()function.
So you might want to preserve and restore the overridden functions after doing the 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'}

