代码是:
from pprint import pprint
d = {"b" : "Maria", "c" : "Helen", "a" : "George"}
pprint(d, width = 1)
输出是:
{'a': 'George',
'b': 'Maria',
'c': 'Helen'}
但是,所需的输出是:
{'b': 'Maria',
'c': 'Helen',
'a': 'George'}
这可以用pprint完成还是有另一种方式?
至于Python 3.7+,dict
保留了插入顺序。对于之前的任何版本,您将需要使用OrderedDict
来保持按键顺序。
虽然,从doc on pprint
:
在计算显示之前,字典按键排序。
这意味着pprint
无论如何都会打破你想要的订单。
json.dumps
虽然可以将pprint.PrettyPrinter
子类化为在显示之前不对键进行排序,但它很繁琐,一个很好的选择是使用json.dumps
来打印您的数据。
import json
from collections import OrderedDict
# For Python 3.6 and prior, use an OrderedDict
d = OrderedDict(b="Maria", c="Helen", a="George")
print(json.dumps(d, indent=1))
{
"b": "Maria",
"c": "Helen",
"a": "George"
}
如果您阅读了pprint.py
的来源,您会在PrettyPrinter._pprint_dict()
中找到负责格式化dicts的方法:
def _pprint_dict(self, object, stream, indent, allowance, context, level):
write = stream.write
write('{')
if self._indent_per_level > 1:
write((self._indent_per_level - 1) * ' ')
length = len(object)
if length:
items = sorted(object.items(), key=_safe_tuple)
self._format_dict_items(items, stream, indent, allowance + 1,
context, level)
write('}')
_dispatch[dict.__repr__] = _pprint_dict
有一行items = sorted(object.items(), key=_safe_tuple)
,所以dict项目总是在处理格式之前先排序,你必须通过复制和粘贴它并删除你自己脚本中的违规行来自己覆盖它:
import pprint as pp
def _pprint_dict(self, object, stream, indent, allowance, context, level):
write = stream.write
write('{')
if self._indent_per_level > 1:
write((self._indent_per_level - 1) * ' ')
length = len(object)
if length:
self._format_dict_items(object.items(), stream, indent, allowance + 1,
context, level)
write('}')
pp.PrettyPrinter._dispatch[dict.__repr__] = _pprint_dict
以便:
pp.pprint({"b" : "Maria", "c" : "Helen", "a" : "George"}, width=1)
将输出(在Python 3.6+中):
{'b': 'Maria',
'c': 'Helen',
'a': 'George'}
您应该使用python的collections库中的OrderedDict来保持顺序不变
from collections import OrderedDict
from pprint import pprint
d = OrderedDict({"b" : "Maria", "c" : "Helen", "a" : "George"})
pprint(d, width = 1)
更新:
由于输出很重要,您可以使用以下代码,它是一个黑客,但您创建一个函数来实现此功能:
from collections import OrderedDict
d = OrderedDict({"b" : "Maria", "c" : "Helen", "a" : "George"})
print('{', end='')
total_len = len(d)
current_index = 1
for key, value in d.items():
print('\''+key+'\': \'' + value+ '\'', end='')
if current_index<total_len:
print(',')
else:
print('}')
current_index += 1
一个更通用的解决方案是使用unittest.mock.patch
覆盖内置的sorted
函数,该函数除了返回给定的第一个参数之外什么都不做:
import pprint
from unittest.mock import patch
def unsorted_pprint(*args, **kwargs):
with patch('builtins.sorted', new=lambda l, **_: l):
orig_pprint(*args, **kwargs)
orig_pprint = pprint.pprint
pprint.pprint = unsorted_pprint
以便:
pprint.pprint({"b" : "Maria", "c" : "Helen", "a" : "George"})
输出:
{'b': 'Maria', 'c': 'Helen', 'a': 'George'}