代码之家  ›  专栏  ›  技术社区  ›  intuited

实现定制漂亮打印机的最佳方法

  •  20
  • intuited  · 技术社区  · 14 年前

    定制 pprint.PrettyPrinter

    的文档 pprint 模块提到方法 PrettyPrinter.format 旨在使自定义格式成为可能。

    我认为可以在子类中重写此方法,但这似乎并不能提供让基类方法应用换行和缩进的方法。

    • 我是不是丢了什么东西?
    • 有没有更好的方法来做这个(例如,另一个模块)?

    选择?

    我查过了 pretty 模块,看起来很有趣,但似乎没有提供一种方法来自定义来自其他模块的类的格式而不修改这些模块。

    我想我要找的是一个允许我提供类型(或者可能是函数)映射的东西,它可以将类型标识为处理节点的例程。处理节点的例程将获取一个节点并返回该节点的字符串表示形式以及子节点列表。等等。

    为什么我要找漂亮的印刷品

    我的最终目标是紧凑地打印docbook格式的自定义格式化部分 xml.etree.ElementTree .

    (我很惊讶没有找到对docbook的更多python支持。也许我错过了什么。)

    我在一个名为 xmlearn 使用的 lxml . 例如,要转储docbook文件,可以:

    xmlearn -i docbook_file.xml dump -f docbook -r book
    

    这真是太差劲了,但它让我得到了我要找的信息。

    新学 还具有其他特性,例如能够构建一个图形图像,并执行转储以显示XML文档中标记之间的关系。这些和这个问题几乎完全无关。

    您还可以执行到任意深度的转储,或者将xpath指定为一组起点。xpath的东西有点过时了docbook特定的格式,所以这并没有得到很好的开发。

    这仍然不是这个问题的真正答案。我仍然希望有一个现成的定制漂亮的打印机在那里某处。

    4 回复  |  直到 12 年前
        1
  •  3
  •   Josh    12 年前

    我的解决方案是用一个简单的包装器替换pprint.prettyprinter,该包装器在调用原始打印机之前格式化找到的任何浮点。

    from __future__ import division
    import pprint
    if not hasattr(pprint,'old_printer'):
        pprint.old_printer=pprint.PrettyPrinter
    
    class MyPrettyPrinter(pprint.old_printer):
        def _format(self,obj,*args,**kwargs):
            if isinstance(obj,float):
                obj=round(obj,4)
            return pprint.old_printer._format(self,obj,*args,**kwargs)
    pprint.PrettyPrinter=MyPrettyPrinter
    
    def pp(obj):
        pprint.pprint(obj)
    
    if __name__=='__main__':
        x=[1,2,4,6,457,3,8,3,4]
        x=[_/17 for _ in x]
        pp(x)
    
        2
  •  2
  •   Community CDub    7 年前

    此问题可能是以下内容的副本:


    使用 pprint.PrettyPrinter

    我看了看 source of pprint . 这似乎表明,为了增强 pprint() ,你需要:

    • 子类 PrettyPrinter
    • 重写 _format()
    • 测试 issubclass() ,
    • (如果不是你的课),传给 *格式()

    替代方案

    我认为一个更好的方法就是拥有自己的 pPrime() ,它遵从于 pprint.pformat 当它不知道发生了什么。

    例如:

    '''Extending pprint'''
    
    from pprint import pformat
    
    class CrazyClass: pass
    
    def prettyformat(obj):
        if isinstance(obj, CrazyClass):
            return "^CrazyFoSho^"
        else:
            return pformat(obj)
    
    def prettyp(obj):
        print(prettyformat(obj))
    
    # test
    prettyp([1]*100)
    prettyp(CrazyClass())
    

    最大的好处是你不依赖 pprint 内构件。它简洁明了。

    缺点是您必须手动处理缩进。

        3
  •  2
  •   saul.shanabrook    6 年前

    如果您想修改默认的漂亮打印机而不进行子类化,可以使用 _dispatch 表上 pprint.PrettyPrinter 班级。您可以看到如何为内部类型(如字典和列表)添加分派的示例 in the source .

    下面是我如何添加自定义漂亮打印机 MatchPy's Operation 类型:

    import pprint
    import matchpy
    
    def _pprint_operation(self, object, stream, indent, allowance, context, level):
        """
        Modified from pprint dict https://github.com/python/cpython/blob/3.7/Lib/pprint.py#L194
        """
        operands = object.operands
        if not operands:
            stream.write(repr(object))
            return
        cls = object.__class__
        stream.write(cls.__name__ + "(")
        self._format_items(
            operands, stream, indent + len(cls.__name__), allowance + 1, context, level
        )
        stream.write(")")
    
    
    pprint.PrettyPrinter._dispatch[matchpy.Operation.__repr__] = _pprint_operation
    

    如果我使用 pprint.pprint 在任何物体上 __repr__ 作为 matchpy.Operation ,它将使用此方法漂亮地打印它。这也适用于子类,只要它们不重写 第二乐章 ,这有点道理!如果你有相同的 第二乐章 你有同样漂亮的印刷行为。

    下面是一个漂亮的打印示例:

    ReshapeVector(Vector(Scalar('1')),
                  Vector(Index(Vector(Scalar('0')),
                               If(Scalar('True'),
                                  Scalar("ReshapeVector(Vector(Scalar('2'), Scalar('2')), Iota(Scalar('10')))"),
                                  Scalar("ReshapeVector(Vector(Scalar('2'), Scalar('2')), Ravel(Iota(Scalar('10'))))")))))
    
        4
  •  1
  •   Carl Smith kyle k    9 年前

    考虑使用 pretty 模块: