前不久,我写了一篇文章回顾 Python 中 print 的发展历史 ,提到了两条发展线索:

  • 明线:早期的 print 语句带有 C 和 Shell 的影子,是个应用程序级的 statement,在最初十几年里,经历过 PEP-214 和 PEP-259 的改进;再到 2009 年的大版本 3.0,由语句改成了 print() 函数,还在 3.3 版本,做过一次功能增强,最终上升成为一等的内置函数。
  • 暗线:介绍了 print 的竞争对手们,像传统的日志模块 logging、调试模块 pdb、主流 IDE 的调试功能,以及后起之秀 PySnooper,它们瞄准着 print 的位置,摩拳擦掌,虎视眈眈。

本文依然跟 print 相关,想介绍的是标准库中的 pprint 模块。

(未经授权,请勿转载。文章首发于:https://mp.weixin.qq.com/s/d1dQH1Fqaj_U3AXKYluhSw)

pprint 是“pretty printer”的简写,“pretty”的含义是“漂亮的、美观的”,还有表示“相当地”的程度语气,因此它的含义便是:(相当)美观的打印。

这是个相当简单却有用的模块,主要用于打印复杂的数据结构对象,例如多层嵌套的列表、元组和字典等。

先看看 print() 打印的一个例子:

mylist = ["Beautiful is better than ugly.", "Explicit is better than implicit.", "Simple is better than complex.", "Complex is better than complicated."]

print(mylist)

# 结果如下:
['Beautiful is better than ugly.', 'Explicit is better than implicit.', 'Simple is better than complex.', 'Complex is better than complicated.']

这是一个简单的例子,全部打印在一行里。

想象一下,如果对象中的元素是多层嵌套的内容(例如复杂的 Json 数据),或者有超多的元素(例如在列表中存了很多 URL 链接),再打印出来会是怎样?

那肯定是一团糟的,不好阅读。

使用 pprint 模块的 pprint() 替代 print(),可以解决如下痛点:

  • 设置合适的行宽度,作适当的换行
  • 设置打印的缩进、层级,进行格式化打印
  • 判断对象中是否出现无限循环,并优化打印内容

1、简单使用

语法:pprint(object, stream=None, indent=1, width=80, depth=None, *,compact=False)

默认的行宽度参数为 80,当打印的字符(character)小于 80 时,pprint() 基本上等同于内置函数 print(),当字符超出时,它会作美化,进行格式化输出:

import pprint

# 打印上例的 mylist
pprint.pprint(mylist) # 打印的元素是换行的(因为超出80字符):
['Beautiful is better than ugly.',
'Explicit is better than implicit.',
'Simple is better than complex.',
'Complex is better than complicated.']

2、设置缩进为 4 个空格(默认为1)

pprint.pprint(mylist, indent=4)

[   'Beautiful is better than ugly.',
'Explicit is better than implicit.',
'Simple is better than complex.',
'Complex is better than complicated.']

3、设置打印的行宽

mydict = {'students': [{'name':'Tom', 'age': 18},{'name':'Jerry', 'age': 19}]}

pprint.pprint(mydict)

# 未超长:
{'students': [{'age': 18, 'name': 'Tom'}, {'age': 19, 'name': 'Jerry'}]} pprint.pprint(mydict, width=20) # 超长1:
{'students': [{'age': 18,
'name': 'Tom'},
{'age': 19,
'name': 'Jerry'}]} pprint.pprint(mydict, width=70) # 超长2:
{'students': [{'age': 18, 'name': 'Tom'},
{'age': 19, 'name': 'Jerry'}]}

4、设置打印的层级(默认全打印)

newlist = [1, [2, [3, [4, [5]]]]]

pprint.pprint(newlist, depth=3)

# 超出的层级会用...表示
[1, [2, [3, [...]]]]

5、优化循环结构的打印

当列表或其它数据结构中出现循环引用时,要完整打印出所有内容是不可能的。

所以 print 作了简化处理,就像上例一样,只打印外层的壳,而不打印内层循环的东西。

这种处理方式是简化了,但没有指出是谁导致了循环,还容易看漏。

pprint() 方法作了改进,遇到无限循环结构时,会表示成<Recursion on typename with id=number> 的格式。

还有个 saferepr() 方法,也是这样优化,而且返回的是个字符串:

newlist = [1, 2]
newlist.insert(0, newlist) # 列表元素指向列表自身,造成循环引用
# 直接 print 的结果是:[[...], 1, 2] pprint.pprint(newlist)
# [<Recursion on list with id=1741283656456>, 1, 2] pprint.saferepr(newlist)
# '[<Recursion on list with id=1741283656456>, 1, 2]'

6、判断是否出现循环结构

有两个方法可以判断一个对象中是否出现无限循环:

pprint.isrecursive(newlist)
# True pprint.isreadable(newlist)
# False

isreadable() 除了能像 isrecursive() 一样判断循环,还能判断该格式化内容是否可被 eval() 重构。

以上就是 pprint 模块的快捷入门介绍,除此之外,还有 pformat() 方法、PrettyPrinter 类,以及某些参数的使用等内容,我觉得没有大用,就不多说了。

如若感兴趣,你可查阅:

最后,还有两个小小的点:

1、用 pprint() 替换 print() 的技巧

在不考虑 print() 函数本身的参数的情况下,可以在引入 pprint 模块后,写上 “print = pprint.pprint”,令 print() 起到改头换面的效果:

import pprint
print = pprint.pprint mylist = ["Beautiful is better than ugly.", "Explicit is better than implicit.", "Simple is better than complex.", "Complex is better than complicated."] print(mylist) # 可对比本文开头的例子
['Beautiful is better than ugly.',
'Explicit is better than implicit.',
'Simple is better than complex.',
'Complex is better than complicated.']

2、国人开发的 beeprint

国内某位 pan 同学在 Github 开源了个beeprint,明显是对标 pprint 的。

项目地址:https://github.com/panyanyany/beeprint

它优化了字典对象的打印,对于从其它语言转过来的同学而言(例如 Java),这是个福音:

它还优化了长文本的打印,支持自定义对象的打印,看起来不错。

但是,其它功能不够齐全,而且作者停止维护两年了,荒废已久……

总体而言,pprint 算是 print() 的轻量级替代,简单实用,极其方便(毕竟是标准库),文档丰富而有保障。

所以,若想要打印美观易读的数据,这个 pprint 标准库,不妨一试哦。

作者简介:豌豆花下猫,生于广东毕业于武大,现为苏漂程序员,有一些极客思维,也有一些人文情怀,有一些温度,还有一些态度。公众号:「Python猫」(python_cat)

公众号【Python猫】, 本号连载优质的系列文章,有喵星哲学猫系列、Python进阶系列、好书推荐系列、技术写作、优质英文推荐与翻译等等,欢迎关注哦。

如何美观地打印 Python 对象?这个标准库可以简单实现的更多相关文章

  1. Python常用的标准库以及第三方库

    Python常用的标准库以及第三方库有哪些?   20个必不可少的Python库也是基本的第三方库 读者您好.今天我将介绍20个属于我常用工具的Python库,我相信你看完之后也会觉得离不开它们.他们 ...

  2. Python OS模块标准库的系统接口及操作方法

    Python OS模块标准库的系统接口及操作方法 os.name 返回当前操作系统名,定义了'posix','nt','mac','os2','ce','java'(我使用win7/python3.1 ...

  3. Python内置模块与标准库

    Python内置模块就是标准库(模块)吗?或者说Python的自带string模块是内置模块吗? 答案是:string不是内置模块,它是标准库.也就是说Python内置模块和标准库并不是同一种东西. ...

  4. C++标准库<string>简单总结

    C++标准库<string>简单总结 在C++中,如果需要对字符串进行处理,那么它自带的标准库<string>无疑是最好的选择,它实现了很多常用的字符处理函数. 要想使用标准C ...

  5. Python常用的标准库以及第三方库有哪些?

    20个必不可少的Python库也是基本的第三方库 读者您好.今天我将介绍20个属于我常用工具的Python库,我相信你看完之后也会觉得离不开它们.他们是: Requests.Kenneth Reitz ...

  6. Python 常用的标准库以及第三方库有哪些?

    作者:史豹链接:https://www.zhihu.com/question/20501628/answer/223340838来源:知乎著作权归作者所有.商业转载请联系作者获得授权,非商业转载请注明 ...

  7. NO.5:自学python之路------标准库,正则表达式

    引言 时间过的好快呀,终于6级也考完了,学习Python的进度也得赶赶了.好的开始这一周的内容. 正文 模块 模块的本质就是‘.py’结尾的文件,它可以用来从逻辑上组织Python代码,它可以是变量. ...

  8. Python中级 —— 07标准库

    标准库学习 1. The Python Standard Library[https://docs.python.org/3.5/library/] ( 3.5.5 Documentation ) 1 ...

  9. python学习笔记系列----(八)python常用的标准库

    终于学到了python手册的最后一部分:常用标准库.这部分内容主要就是介绍了一些基础的常用的基础库,可以大概了解下,在以后真正使用的时候也能想起来再拿出来用. 8.1 操作系统接口模块:OS OS模块 ...

随机推荐

  1. c语言进阶5-递归算法

    一.  什么是递归 程序调用自身的编程技巧称为递归( recursion). 递归做为一种算法在程序设计语言中广泛应用. 一个过程或函数在其定义或说明中有直接或间接调用自身的一种方法,它通常把一个大型 ...

  2. 基于tcp协议的登录,文件上传和下载

    ​ [1]先登录,登录不成功循环登录,直到成功.登录成功后可以选择上传或者下载,上传有对应的文件,可选择上传哪个:下载有对应的文件,可选择下载哪个 ​ [2]登录,上传,下载时最好设置状态码,客户端和 ...

  3. STL 优先队列 用法

    今天做题用到了优先队列 对它的用法还不是很熟悉 现在整理一下. 需要的库 #include<queue> using namespace std; 不过我都用bits/stdc++.h.. ...

  4. python课堂整理10---局部变量与全局变量

    一.局部变量与全局变量 1. 没有缩进,顶头写的变量为全局变量 2. 在子程序里定义的变量为局部变量 3. 只有函数能把变量私有化 name = 'lhf' #全局变量 def change_name ...

  5. Java生鲜电商平台-统一异常处理及架构实战

    Java生鲜电商平台-统一异常处理及架构实战 补充说明:本文讲得比较细,所以篇幅较长. 请认真读完,希望读完后能对统一异常处理有一个清晰的认识. 背景 软件开发过程中,不可避免的是需要处理各种异常,就 ...

  6. TreeSet类的排序

    TreeSet支持两种排序方法:自然排序和定制排序.TreeSet默认采用自然排序. 1.自然排序 TreeSet会调用集合元素的compareTo(Object obj)方法来比较元素之间大小关系, ...

  7. 在WPF中嵌入WebBrowser可视化页面

    无论是哪种C/S技术,涉及数据可视化就非常的累赘了,当然大神也一定有,只不过面向大多数人,还是通过网页来实现,有的时候不想把这两个功能分开,一般会是客户的原因,所以我们打算在WPF中嵌入WebBrow ...

  8. js实现3D切换效果

    今天分享一个3d翻转动画效果,js+css3+h5实现,没有框架. 先看下html部分: <div class="box"> <ul> <li> ...

  9. linux字符设备驱动中内核如何调用驱动入口函数 一点记录

    /* 内核如何调用驱动入口函数 ? *//* 答: 使用module_init()函数,module_init()函数定义一个结构体,这个结构体里面有一个函数指针,指向first_drv_init() ...

  10. Redis优化建议

    优化的一些建议 1.尽量使用短的key 当然在精简的同时,不要完了key的"见名知意".对于value有些也可精简,比如性别使用0.1. 2.避免使用keys * keys *, ...