太強了!將你如何優雅&美觀地 print Python 對象

(給機器學習算法與Python學習加星標,提升AI技能) 

前不久,我寫了一篇文章回顧 Python 中 print 的發展歷史,提到了兩條發展線索:

  • 明線:早期的 print 語句帶有 C 和 Shell 的影子,是個應用程序級的 statement,在最初十幾年裏,經歷過 PEP-214 和 PEP-259 的改進;再到 2009 年的大版本 3.0,由語句改成了 print() 函數,還在 3.3 版本,做過一次功能增強,最終上升成爲一等的內置函數。

  • 暗線:介紹了 print 的競爭對手們,像傳統的日誌模塊 logging、調試模塊 pdb、主流 IDE 的調試功能,以及後起之秀 PySnooper,它們瞄準着 print 的位置,摩拳擦掌,虎視眈眈。

本文依然跟 print 相關,想介紹的是標準庫中的 pprint 模塊。

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 類,以及某些參數的使用等內容,我覺得沒有大用,就不多說了。

如若感興趣,你可查閱:

官方介紹:https://docs.python.org/zh-cn/3/library/pprint.html

源碼地址:https://github.com/python/cpython/blob/3.7/Lib/pprint.py

最後,還有兩個小小的點:

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 標準庫,不妨一試哦。

推薦閱讀
做過這個NLP項目的面試通過率高達 90%!!

15 個邊玩遊戲邊學編程的網站

Python 中 3 個不可思議的返回

【贈書】曾因「搶車位」出圈兒,神奇的Mask R-CNN瞭解一下?

【教程】還不會用Git的程序員,這個項目讓你邊玩邊學


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章