2015-05-05 3 views
12

Я пробовал pprint от pprint, но его выход - это только одна строка, нет многострочного выхода и нет отступа.Pretty print namedtuple

+4

Можете ли вы привести пример объекта, который вы хотите распечатать и как вы хотите, чтобы напечатанный вывод отображался? – TigerhawkT3

+1

Что вы ожидали? Если вам нужно больше контролировать, как он печатает, создайте пользовательский объект и определите '__repr__'. – jonrsharpe

ответ

8

Я использую метод namedtuple _asdict.

Однако, возвращает OrderedDict который pprint не отступа, поэтому я преобразовать его в dict:

>>> Busbar = namedtuple('Busbar', 'id name voltage') 
>>> busbar = Busbar(id=102, name='FACTORY', voltage=21.8) 

С pprint и dict:

>>> from pprint import pprint 
>>> pprint(dict(busbar._asdict())) 
{'id': 102, 
'name': 'FACTORY', 
'voltage': 21.8} 
4

pprint PrettyPrinter в Python 3 гораздо более расширяема, чем в Python 2. Вы можете создать свой собственный принтер, как показано ниже, чтобы добавить методы для объекта, который вы хотите обработать, не слишком много перепутывая с помощью «частного» метода pprint ds и атрибуты.

Вы можете посмотреть онлайн пример здесь: https://repl.it/HkDd/1

from io import StringIO 
import pprint 

class MyPrettyPrinter(pprint.PrettyPrinter): 
    def format_namedtuple(self, object, stream, indent, allowance, context, level): 
     # Code almost equal to _format_dict, see pprint code 
     write = stream.write 
     write(object.__class__.__name__ + '(') 
     object_dict = object._asdict() 
     length = len(object_dict) 
     if length: 
      # We first try to print inline, and if it is too large then we print it on multiple lines 
      inline_stream = StringIO() 
      self.format_namedtuple_items(object_dict.items(), inline_stream, indent, allowance + 1, context, level, inline=True) 
      max_width = self._width - indent - allowance 
      if len(inline_stream.getvalue()) > max_width: 
       self.format_namedtuple_items(object_dict.items(), stream, indent, allowance + 1, context, level, inline=False) 
      else: 
       stream.write(inline_stream.getvalue()) 
     write(')') 

    def format_namedtuple_items(self, items, stream, indent, allowance, context, level, inline=False): 
     # Code almost equal to _format_dict_items, see pprint code 
     indent += self._indent_per_level 
     write = stream.write 
     last_index = len(items) - 1 
     if inline: 
      delimnl = ', ' 
     else: 
      delimnl = ',\n' + ' ' * indent 
      write('\n' + ' ' * indent) 
     for i, (key, ent) in enumerate(items): 
      last = i == last_index 
      write(key + '=') 
      self._format(ent, stream, indent + len(key) + 2, 
         allowance if last else 1, 
         context, level) 
      if not last: 
       write(delimnl) 

    def _format(self, object, stream, indent, allowance, context, level): 
     # We dynamically add the types of our namedtuple and namedtuple like 
     # classes to the _dispatch object of pprint that maps classes to 
     # formatting methods 
     # We use a simple criteria (_asdict method) that allows us to use the 
     # same formatting on other classes but a more precise one is possible 
     if hasattr(object, '_asdict') and type(object).__repr__ not in self._dispatch: 
      self._dispatch[type(object).__repr__] = MyPrettyPrinter.format_namedtuple 
     super()._format(object, stream, indent, allowance, context, level) 

и использовать его так:

from collections import namedtuple 

Segment = namedtuple('Segment', 'p1 p2') 
# Your own namedtuple-like class 
class Node: 
    def __init__(self, x, y, segments=[]): 
     self.x = x 
     self.y = y 
     self.segments = segments 

    def _asdict(self): 
     return {"x": self.x, "y": self.y, "segments": self.segments} 

    # Default repr 
    def __repr__(self): 
     return "Node(x={}, y={}, segments={})".format(self.x, self.y, self.segments) 

# A circular structure for the demo 
node = Node(0, 0) 
segments = [ 
    Segment(node, Node(1, 1)), 
    Segment(node, Node(2, 1)), 
    Segment(node, Node(1, 2, segments=[ 
     Segment(Node(2, 3), Node(1, 1)), 
    ])), 
] 
node.segments = segments 

pp = MyPrettyPrinter(indent=2, depth=2) 
pp.pprint(node) 

выходы

Node(
    x=0, 
    y=0, 
    segments=[ Segment(
       p1=<Recursion on Node with id=139778851454536>, 
       p2=Node(x=1, y=1, segments=[])), 
       Segment(
       p1=<Recursion on Node with id=139778851454536>, 
       p2=Node(x=2, y=1, segments=[])), 
       Segment(
       p1=<Recursion on Node with id=139778851454536>, 
       p2=Node(x=1, y=2, segments=[...]))])