Python довольно печатает словарь списков, сокращает длинные списки
У меня есть словарь списков, и списки довольно длинные. Как я могу напечатать его так, чтобы отображалось только несколько элементов списка? Очевидно, что я могу написать для этого настраиваемую функцию, но есть ли встроенный способ или библиотека, которая может это сделать? Например, при печати больших кадров данных 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', '...']
}
Ответы
Ответ 1
Если бы не красивая печать, то был бы reprlib
: безопасная, элегантная и настраиваемая обработка глубоко вложенных и рекурсивных/самореферентных структур данных - это то, для чего оно было сделано.
Однако получается, что reprlib
и pprint
не тривиально, по крайней мере, я не мог придумать чистый способ, не нарушая (некоторые) из-за довольно печатных аспектов.
Таким образом, вместо этого здесь решение, которое просто подклассифицирует 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, кортежей, наборов, фризонсет,... для этого класса, чтобы быть общего использования.
Ответ 2
Вы можете использовать модуль 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']}
Ответ 3
Вы можете использовать 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()
Ответ 4
Эта рекурсивная функция, которую я написал, делает то, о чем вы просите. Вы также можете выбрать желаемый отступ
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']
Ответ 5
Используйте 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, ...], ...}'