PrettyPrinter是Python 3.6 及以上版本中的一个功能强大、支持语法高亮、描述性的美化打印包。它使用了改进的Wadler-Leijen布局算法,和Haskell打印美化库中的prettyprinter以及anti-wl-pprint、 JavaScript的Prettier、Ruby的prettypreinter.rb 以及 IPython的Ipython.lib.pretty类似。Python的PrettyPrinter集以上众家之所长,并在此基础上继续改进,因此也成为目前Python最强大的美化输出工具。

以下是使用PrettyPrinter输出结果的截图:


为什么Python还需要额外的美化打印包呢?

无论是IDE还是开发者手动运行命令,将数据打印到屏幕上是程序运行过程中程序员和数值交互的最基础的界面。改进该界面有助于提升开发体验和生产效率。Python本身和第三方库都提供了一些工具来达到此目的:

__repr__和__str__两个下划线方法返回普通字符串。__repr__应该尽可能返回语法正确的Python表达式,断言判断失败及控制台计算结果打印最常用的就是该方法。由于其完全基于字符串格式化,因此并不具备美化打印的功能。

标准库中的pprint模块为dicts, lists, tuples, sets, and frozensets等内置数据类型提供了美化打印的功能。它将__repr__方法应用在用户自定义的类实例上。然而,它使用了非常贪婪的布局算法,导致在很多情况下的美化打印出现问题。由于自定义的美化打印受__repr__所限制,pprint的作用也就限制于内置数据类型了。

第三方库pprintpp是对pprint的改进及替代方案,也可以对输出进行优化,不过和pprint一样受限于__repr__使用的代码美化定义。

IPython中默认的打印模块IPython.lib.pretty的目标是pprint更进阶的替代方案。和pprint相比,它在很多方面都表现得更好:大多数情况下算法都能对输出进行美化,而且提供了针对用户自定义类型美化输出的定义工具,能和输出的其他部分实现比较好的结合。不过,为了实现你自己的美化打印方式,你需要对布局算法有所了解。

另外,该API 也有一些与生俱来的副作用:调用美化打印工具将数据直接推送至布局缓冲区,不允许原始布局对数据进行初步检测。

以上所有工具都达不到我对美化打印体验的要求,因此我开始做以下几点改进:

实现一个能尽可能多的美化打印的算法,即便在效率上做出一些牺牲。花十分之一秒对输出结果进行美化是非常划算的,因为当你需要在结果中寻找自己需要的数据时它将为你节约两秒钟的时间。

实现一个超级简单、描述性的接口来实现用户自定义的美化打印工具。Python成员几乎不会重写__repr__方法,因为这很痛苦;几乎没有人愿意为用户定义的类型编写整齐打印规则,除非类型非常简单。

实现不会在无效Python语法上中断的语法高亮显示。并不是所有__repr__方法都会返回有效的语法,一旦发生语法错误会打断正常的语法高亮。

新的代码美化包的使用体验令我非常惊讶。算法运行的很出色,效率也满足需求。而用户自定义美化规则的方法也很简单,仅仅需要了解两个描述性的函数 register_pretty和pretty_call即可。语法高亮看上去非常漂亮,且不会被无效语法处中断。特别是语法高亮,会使你很难再回到普通的美化打印工具,它大大提升了程序员的开发体验。

最有趣的改进是描述性API,下面是它的工作原理。

简单、描述性的API

在PrettyPrinter中定义输出美化方法主要基于(创建)函数调用。所有非字符的Python值都需要用函数结果表示。该库的主力函数是pretty_call, 它允许你来描述PrettyPrinter应该输出何种类型的函数调用。下面就是pretty_call调用的一个例子:

from prettyprinter import pretty_call# ctx is available in pretty printer definitions
layout_primitive = pretty_call(ctx, sorted, [5, 3, 6, 1], reverse=True)

PrettyPrinter处理原始布局的过程类似于以下语句:

sorted([5, 3, 6, 1], reverse=True)

(第一个参数ctx允许用户控制案例中[5,3,6,1]列表中嵌套的数据,reverse参数的True值依据此进行渲染。大部分情况都直接使用默认值即可。)

上面介绍了如何使用Pretty_call,接下来定义我们自己的类型。

class MyClass:def __init__(self, one, two):self.one = oneself.two = two

使用register_pretty修饰符,可以为MyClass类定义美化方式:

from prettyprinter import register_pretty, pretty_call@register_pretty(MyClass)
def pretty_myclass(value, ctx):return pretty_call(ctx, MyClass, one=value.one, two=value.two)

cpprint的输出如下:

>>> from prettyprinter import cpprint
>>> cpprint(MyClass(1, 2))
MyClass(one=1, two=2)

带状态实例的表示

调用函数的一个缺陷是无法很好的表示带状态的实例。通常你想要额外输出一些信息来表示实例的状态。PrettyPrinter使用解释性评论解决了这一问题,我对这一强大的特性颇为满意。使用评论来标注Python值(或者表示Python值的原始布局),该评论将神奇的出现在输出的结果中。

假如我们定义了一个包含其连接与断开两个状态的Connection类:

class Connection:def __init__(self, hostname):self.hostname = hostnameself.is_open = Falsedef open(self):self.is_open = Truedef close(self):self.is_open = False

如果想得到以下输出:

Connection('http://example.com')  # Status: Open

可以通过如下定义来实现:

from prettyprinter import register_pretty, pretty_call, comment@register_pretty(Connection)
def pretty_connection(connection, ctx):status_text = ('Status: Open'if connection.is_openelse 'Status: Closed')return comment(pretty_call(ctx,Connection,connection.hostname,),status_text)

结论

我非常享受将PrettyPrinter作为开发工具包的一部分。单独一篇文章只能粗略分享一些点,还有很多有趣的部分等待你去探索,强烈推荐大家尝试一下!在IPython中使用效果更佳,因为交互式解释器环境中的所有结果都可以自动使用PrettyPrinter打印输出。文档中有对该命令的设置的说明。

点击source code on GitHub查看该项目的源码,文档在documentation on readthedocs.io(目前可能还略显简陋)。包中内置了针对Django模型、QuerySets以及使用attrs包创建的所有类的现成的定义。因此如果你恰好也用到了其中的某个,毫无疑问你会想马上试试它的!

原文发布时间为:2018-12-16
本文作者:上海小胖
本文来自云栖社区合作伙伴“ Python专栏”,了解相关信息可以关注“xpchuiit”微信公众号

Python | 用PrettyPrinter,让Python输出更漂亮,你值得拥有相关推荐

  1. 12月17日云栖精选夜读 | 用PrettyPrinter,让Python输出更漂亮,你值得拥有

    PrettyPrinter是Python 3.6 及以上版本中的一个功能强大.支持语法高亮.描述性的美化打印包.它使用了改进的Wadler-Leijen布局算法,和Haskell打印美化库中的pret ...

  2. 12月17日云栖精选夜读 | 用PrettyPrinter,让Python输出更漂亮,你值得拥有...

    PrettyPrinter是Python 3.6 及以上版本中的一个功能强大.支持语法高亮.描述性的美化打印包.它使用了改进的Wadler-Leijen布局算法,和Haskell打印美化库中的pret ...

  3. python 打印类型_让Python输出更漂亮:PrettyPrinter

    PrettyPrinter是Python 3.6 及以上版本中的一个功能强大.支持语法高亮.描述性的美化打印包.它使用了改进的Wadler-Leijen布局算法,和Haskell打印美化库中的pret ...

  4. python符号计算 漂亮地打印出来_让Python输出更漂亮:PrettyPrinter

    PrettyPrinter是Python 3.6 及以上版本中的一个功能强大.支持语法高亮.描述性的美化打印包.它使用了改进的Wadler-Leijen布局算法,和Haskell打印美化库中的pret ...

  5. 让Python输出更漂亮

    print 默认输出是换行的,如果要实现不换行需要在变量末尾加上 end="": student_age = 18 print("学生的年龄为:", stude ...

  6. 分享一个让 Ping 的输出更简单易读方法

    众所周知,ping 命令可以用来检查目标主机是否可达.使用 ping 命令的时候,会发送一个 ICMP Echo 请求,通过目标主机的响应与否来确定目标主机的状态.如果你经常使用 ping 命令,你可 ...

  7. Python语法-1-变量、输出、List列表、tuple元组、条件判断和循环等重要基础知识

    针对Openmv3上的Python应用(摘录带修改) 输出 1. 用print()在括号中加上字符串,就可以向屏幕上输出指定的文字.比如输出'hello, world',用代码实现如下: print( ...

  8. python中图片绘制和输出相关库的原理详解

    Python在图片绘制和输出方面的发展历史可以追溯到20世纪90年代,当时的主要库是Python Imaging Library (PIL),用于处理图像文件和生成图像.PIL是Python中最早的图 ...

  9. python起步输入-Python编程起步——输入与输出

    Python编程起步--输入与输出 通常,任何计算机程序都是为了执行一个特定的任务,比如:统计一个班同学的平均英语成绩,在显示器上画出一个半径为100个像素的红色圆圈,或者在视频播放器上播放一段指定的 ...

最新文章

  1. python如何安装torch_PyTorch安装与基本使用详解
  2. python elasticsearch 入门教程(一)
  3. Jmeter-3.0的源码导入eclipse并执行
  4. vtkpolydata图形着色
  5. Cisco 利用 802.1X、动态VLAN和DHCP技术实现方案
  6. PortAudio(v19) 在vs2010上的环境搭建
  7. Emgu-WPF学习使用-阈值化
  8. linux ssh远程登陆报警提醒
  9. 502 proxy error解决方法_老大说,网上这种获取真实IP地址的方法不对,我不信......
  10. 开源GIS(十)——openlayers中加载在线标准与自定义切片
  11. python ocr识别身份证_Python+opencv+pytesseract实现身份证号码识别
  12. 高通CSR8675蓝牙音频芯片怎么样?CSR8675处理器参数介绍
  13. XLua官方教程 06 热更新实例 hotfix样例
  14. K-means(K均值原型聚类)
  15. 全球主要高光谱遥感卫星介绍
  16. BUUCTF笔记之Misc系列部分WriteUp(二)
  17. 学习PCB之pcb器件的绘制
  18. uiq3.0sdk最终版模拟器显示中文
  19. python 列表的操作
  20. SpringBoot集成TkMybatis

热门文章

  1. python在windows下import其他模块的注意事项
  2. 如何成为月入过万的斜杠青年
  3. java自动装箱性能
  4. 基于用户画像 《列变行》 特征打标显示
  5. 【×××系列八】Dynamic Multipoint *** for IPv6 详解
  6. 在vs里不重启模拟器进行Symbian调试
  7. Mysql:命令选项、配置选项、(全局、会话)系统变量、状态变量:命令选项...
  8. python cmdb资产_SuperCMDB - 资产管理+跳板审计
  9. Python pickle模块:实现Python对象的持久化存储
  10. 牛批了,1行python代码就可实现炫酷可视化