2015-05-05 20 views
12

Ho provato pprint da pprint, ma il suo output è solo una riga, non c'è output multilinea e nessuna indentazione.Pretty print namedtuple

+4

Può fare un esempio di oggetto che si desidera stampare e come si desidera che l'output stampato appaia? – TigerhawkT3

+1

Cosa ti aspettavi? Se hai bisogno di più controllo su come si stampa, crea un oggetto personalizzato e definisci '__repr__'. – jonrsharpe

risposta

8

Uso il metodo _asdict di namedtuple.

Tuttavia, restituisce un OrderedDict che pprint volontà non trattino, così ho convertirlo in un dict:

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

Con pprint e dict:

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

Il pprint PrettyPrinter in Python 3 è molto più estensibile di quanto non fosse in Python 2. Potresti creare la tua stampante come di seguito per aggiungere metodi per l'oggetto che vuoi gestire senza troppi problemi con il metho "privato" pprint ds e attributi.

È possibile vedere un esempio on-line qui: 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) 

e usarlo in questo modo:

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) 

uscite

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=[...]))])