2015-05-05 13 views
12

Tôi đã thử pprint từ pprint, nhưng đầu ra của nó chỉ là một dòng, không có đầu ra nhiều dòng và không có thụt đầu dòng.Pretty print namedtuple

+4

Bạn có thể cho một ví dụ về đối tượng mà bạn muốn để in và cách bạn muốn đầu ra in xuất hiện? – TigerhawkT3

+1

Bạn mong đợi điều gì? Nếu bạn cần kiểm soát nhiều hơn cách nó in ra, hãy tạo một đối tượng tùy chỉnh và xác định '__repr__'. – jonrsharpe

Trả lời

8

Tôi sử dụng phương thức _asdict của namedtuple.

Tuy nhiên, nó sẽ trả về một OrderedDictpprint sẽ không thụt lề, vì vậy tôi chuyển nó sang một dict:

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

Với pprintdict:

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

Các pprint PrettyPrinter bằng Python 3 có thể mở rộng nhiều hơn so với trong Python 2. Bạn có thể tạo máy in của riêng mình như dưới đây để thêm các phương thức cho đối tượng mà bạn muốn xử lý mà không làm rối tung quá nhiều với "metho" riêng tư ds và thuộc tính.

Bạn có thể thấy một ví dụ trực tuyến tại đây: 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) 

và sử dụng nó như vậy:

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) 

đầu ra

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