11

代码是:

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 完成还是有其他方法?

4

5 回答 5

12

Python 3.8 或更新版本:

您可以使用sort_dicts=False它来防止它按字母顺序对它们进行排序:

pprint.pprint(data, sort_dicts=False)

Python 3.7 或更早版本:

由于 Python 3.7(或 cPython 的 3.6),dict保留了插入顺序。对于之前的任何版本,您都需要使用OrderedDict来保持密钥的顺序。

虽然,从文档上pprint

字典在计算显示之前按键排序。

这意味着pprint无论如何都会破坏您想要的订单。

替代方法:

您还可以使用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"
}
于 2018-08-10T14:50:41.810 回答
4

如果您阅读源代码,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'}
于 2018-08-10T14:43:38.633 回答
3

从 Python 3.8 开始, pprint 有一个sort_dicts关键字参数,您可以设置它以防止它按字母顺序对字典键进行排序。如果将其设置为 false,它将使用字典的默认顺序(例如插入顺序)。

例子:

>>> from pprint import pprint
>>> pprint(dict(z=0, a=1), sort_dicts=False)
{'z': 0, 'a': 1}
于 2020-05-08T15:37:49.730 回答
3

一个更通用的解决方案是使用一个函数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'}
于 2019-04-13T00:58:10.053 回答
2

您应该使用 python 集合库中的 OrderedDict 来保持排序不变

from collections import OrderedDict
from pprint import pprint
d = OrderedDict({"b" : "Maria", "c" : "Helen", "a" : "George"})
pprint(d, width = 1)

更新:

由于输出很重要,您可以使用以下代码,这是一个 hack,但您创建了一个函数来实现此功能:

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
于 2018-08-10T14:18:06.287 回答