【问题标题】:Python pretty print dictionary of lists, abbreviate long listsPython漂亮的打印列表字典,缩写长列表
【发布时间】:2016-11-26 18:15:46
【问题描述】:

我有一本列表字典,而且列表很长。如何以仅显示列表中的几个元素的方式打印它?显然,我可以为此编写一个自定义函数,但是是否有任何内置方法或库可以实现这一点?例如,在打印大数据帧时,pandas 会以很短的方式很好地打印它。

这个例子更好地说明了我的意思:

obj = {'key_1': ['EG8XYD9FVN',
  'S2WARDCVAO',
  'J00YCU55DP',
  'R07BUIF2F7',
  'VGPS1JD0UM',
  'WL3TWSDP8E',
  'LD8QY7DMJ3',
  'J36U3Z9KOQ',
  'KU2FUGYB2U',
  'JF3RQ315BY'],
 'key_2': ['162LO154PM',
  '3ROAV881V2',
  'I4T79LP18J',
  'WBD36EM6QL',
  'DEIODVQU46',
  'KWSJA5WDKQ',
  'WX9SVRFO0G',
  '6UN63WU64G',
  '3Z89U7XM60',
  '167CYON6YN']}

期望的输出:像这样:

{'key_1':
    ['EG8XYD9FVN', 'S2WARDCVAO', '...'],
 'key_2':
    ['162LO154PM', '3ROAV881V2', '...']
}

【问题讨论】:

  • 您可能还想看看repr module(Py3 中的reprlib),尤其是maxlist 设置:rep = Repr(); rep.maxlist = 3; print rep.repr(obj) 现在将其与pprint 结合起来才是真正的挑战.
  • 太棒了!这是最好的答案,正是我所需要的。你可以添加作为答案吗? @LukasGraf
  • Michael Hoff 似乎已经在研究 reprlib 答案,所以我只是赞成 :)
  • 这不是缩写!实例化Repr 类并设置maxlist 是关键!
  • 确实有,只是maxlist的默认是6,所以不太明显。另请注意,__builtins__.repr()repr.repr() 不同(是的,命名在 Python 2.x 中确实没有帮助)。

标签: python list dictionary pretty-print


【解决方案1】:

你可以使用IPython.lib.pretty

from IPython.lib.pretty import pprint

> pprint(obj, max_seq_length=5)
{'key_1': ['EG8XYD9FVN',
  'S2WARDCVAO',
  'J00YCU55DP',
  'R07BUIF2F7',
  'VGPS1JD0UM',
  ...],
 'key_2': ['162LO154PM',
  '3ROAV881V2',
  'I4T79LP18J',
  'WBD36EM6QL',
  'DEIODVQU46',
  ...]}

> pprint(dict(map(lambda i: (i, range(i + 5)), range(100))), max_seq_length=10)
{0: [0, 1, 2, 3, 4],
 1: [0, 1, 2, 3, 4, 5],
 2: [0, 1, 2, 3, 4, 5, 6],
 3: [0, 1, 2, 3, 4, 5, 6, 7],
 4: [0, 1, 2, 3, 4, 5, 6, 7, 8],
 5: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9],
 6: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, ...],
 7: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, ...],
 8: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, ...],
 9: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, ...],
 ...}

对于旧版本的 IPython,您可能会利用 RepresentationPrinter

from IPython.lib.pretty import RepresentationPrinter
import sys

def compact_pprint(obj, max_seq_length=10):
    printer = RepresentationPrinter(sys.stdout)
    printer.max_seq_length = max_seq_length
    printer.pretty(obj)
    printer.flush()

【讨论】:

  • 可能是因为网上有些混蛋
【解决方案2】:

如果不是为了漂亮的打印,reprlib 模块将是可行的方法:对深度嵌套和递归/自引用数据结构进行安全、优雅和可定制的处理就是它的目的。

但是,事实证明,将 reprlibpprint 模块组合起来并非易事,至少我无法在不破坏(某些)漂亮打印方面的情况下想出一个干净的方法。

因此,这里有一个解决方案,它只是将PrettyPrinter 子类化以根据需要裁剪/缩写列表:

from pprint import PrettyPrinter


obj = {
    'key_1': [
        'EG8XYD9FVN', 'S2WARDCVAO', 'J00YCU55DP', 'R07BUIF2F7', 'VGPS1JD0UM',
        'WL3TWSDP8E', 'LD8QY7DMJ3', 'J36U3Z9KOQ', 'KU2FUGYB2U', 'JF3RQ315BY',
    ],
    'key_2': [
        '162LO154PM', '3ROAV881V2', 'I4T79LP18J', 'WBD36EM6QL', 'DEIODVQU46',
        'KWSJA5WDKQ', 'WX9SVRFO0G', '6UN63WU64G', '3Z89U7XM60', '167CYON6YN',
    ],
    # Test case to make sure we didn't break handling of recursive structures
    'key_3': [
        '162LO154PM', '3ROAV881V2', [1, 2, ['a', 'b', 'c'], 3, 4, 5, 6, 7],
        'KWSJA5WDKQ', 'WX9SVRFO0G', '6UN63WU64G', '3Z89U7XM60', '167CYON6YN',
    ]
}


class CroppingPrettyPrinter(PrettyPrinter):

    def __init__(self, *args, **kwargs):
        self.maxlist = kwargs.pop('maxlist', 6)
        return PrettyPrinter.__init__(self, *args, **kwargs)

    def _format(self, obj, stream, indent, allowance, context, level):
        if isinstance(obj, list):
            # If object is a list, crop a copy of it according to self.maxlist
            # and append an ellipsis
            if len(obj) > self.maxlist:
                cropped_obj = obj[:self.maxlist] + ['...']
                return PrettyPrinter._format(
                    self, cropped_obj, stream, indent,
                    allowance, context, level)

        # Let the original implementation handle anything else
        # Note: No use of super() because PrettyPrinter is an old-style class
        return PrettyPrinter._format(
            self, obj, stream, indent, allowance, context, level)


p = CroppingPrettyPrinter(maxlist=3)
p.pprint(obj)

maxlist=3 的输出:

{'key_1': ['EG8XYD9FVN', 'S2WARDCVAO', 'J00YCU55DP', '...'],
 'key_2': ['162LO154PM',
           '3ROAV881V2',
           [1, 2, ['a', 'b', 'c'], '...'],
           '...']}

maxlist=5 的输出(触发将列表拆分为单独的行):

{'key_1': ['EG8XYD9FVN',
           'S2WARDCVAO',
           'J00YCU55DP',
           'R07BUIF2F7',
           'VGPS1JD0UM',
           '...'],
 'key_2': ['162LO154PM',
           '3ROAV881V2',
           'I4T79LP18J',
           'WBD36EM6QL',
           'DEIODVQU46',
           '...'],
 'key_3': ['162LO154PM',
           '3ROAV881V2',
           [1, 2, ['a', 'b', 'c'], 3, 4, '...'],
           'KWSJA5WDKQ',
           'WX9SVRFO0G',
           '...']}

注意事项:

  • 这将创建列表的副本。根据数据结构的大小,这在内存使用方面可能非常昂贵。
  • 这只处理列表的特殊情况。必须为 dicts、tuples、sets、frozensets 实现等效的行为,......才能使此类具有一般用途。

【讨论】:

  • 有趣的是,我有一个类似的原型。但我不喜欢您为实现字典截断而必须采取的步骤。 +1 努力!
【解决方案3】:

使用reprlib。格式不是那么漂亮,但实际上是缩写。

> import repr
> repr.repr(map(lambda _: range(100000), range(10)))
'[[0, 1, 2, 3, 4, 5, ...], [0, 1, 2, 3, 4, 5, ...], [0, 1, 2, 3, 4, 5, ...], [0, 1, 2, 3, 4, 5, ...], [0, 1, 2, 3, 4, 5, ...], [0, 1, 2, 3, 4, 5, ...], ...]'
> repr.repr(dict(map(lambda i: (i, range(100000)), range(10))))
'{0: [0, 1, 2, 3, 4, 5, ...], 1: [0, 1, 2, 3, 4, 5, ...], 2: [0, 1, 2, 3, 4, 5, ...], 3: [0, 1, 2, 3, 4, 5, ...], ...}'

【讨论】:

  • 是的。 “缩写”部分,或处理递归/自引用结构正是它的目的。不幸的是,如何将它与漂亮的打印(换行符,缩进,...)结合起来并不明显。
【解决方案4】:

您可以使用pprint 模块:

pprint.pprint(obj)

会输出:

{'key_1': ['EG8XYD9FVN',
           'S2WARDCVAO',
           'J00YCU55DP',
           'R07BUIF2F7',
           'VGPS1JD0UM',
           'WL3TWSDP8E',
           'LD8QY7DMJ3',
           'J36U3Z9KOQ',
           'KU2FUGYB2U',
           'JF3RQ315BY'],
 'key_2': ['162LO154PM',
           '3ROAV881V2',
           'I4T79LP18J',
           'WBD36EM6QL',
           'DEIODVQU46',
           'KWSJA5WDKQ',
           'WX9SVRFO0G',
           '6UN63WU64G',
           '3Z89U7XM60',
           '167CYON6YN']}

还有,

pprint.pprint(obj,depth=1)

会输出:

{'key_1': [...], 'key_2': [...]}

还有,

pprint.pprint(obj,compact=True)

会输出:

{'key_1': ['EG8XYD9FVN', 'S2WARDCVAO', 'J00YCU55DP', 'R07BUIF2F7',
           'VGPS1JD0UM', 'WL3TWSDP8E', 'LD8QY7DMJ3', 'J36U3Z9KOQ',
           'KU2FUGYB2U', 'JF3RQ315BY'],
 'key_2': ['162LO154PM', '3ROAV881V2', 'I4T79LP18J', 'WBD36EM6QL',
           'DEIODVQU46', 'KWSJA5WDKQ', 'WX9SVRFO0G', '6UN63WU64G',
           '3Z89U7XM60', '167CYON6YN']}

【讨论】:

  • pprint.pprint(obj,depth=1) 是最接近我需要的东西。我想没有内置的方法可以只打印列表的第一个元素,然后将... 用于其余部分。喜欢{'key_': ['EG8XYD9FVN', ...]
【解决方案5】:

我写的这个递归函数可以满足你的要求。你也可以选择你想要的缩进

def pretty(d, indent=0):
    for key in sorted(d.keys()):
        print '\t' * indent + str(key)
        if isinstance(d[key], dict):
            pretty(d[key], indent+1)
        else:
            print '\t' * (indent+1) + str(d[key])

你的字典的输出是:

key_1
    ['EG8XYD9FVN', 'S2WARDCVAO', 'J00YCU55DP', 'R07BUIF2F7', 'VGPS1JD0UM', 'WL3TWSDP8E', 'LD8QY7DMJ3', 'J36U3Z9KOQ', 'KU2FUGYB2U', 'JF3RQ315BY']
key_2
    ['162LO154PM', '3ROAV881V2', 'I4T79LP18J', 'WBD36EM6QL', 'DEIODVQU46', 'KWSJA5WDKQ', 'WX9SVRFO0G', '6UN63WU64G', '3Z89U7XM60', '167CYON6YN']

【讨论】:

  • 如果您将最后一行更改为print '\t' * (indent+1) + str(d[key][:2]) + '...',它将与我的意思相似。不想要整个列表
  • 哦,明白了,我以为你写了......因为你不想把整个事情再写出来,我的误会!
猜你喜欢
  • 2020-10-23
  • 2020-11-10
  • 2012-10-24
  • 1970-01-01
  • 2011-01-02
  • 2022-01-22
  • 2016-03-08
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多