經驗法則
Python 有好幾種 string formatting 的作法,我個人決定使用情境的經驗法則如下:
- printf-style 的
%
:避免使用;除非有特殊考量,像是這個 logging performance 的例子。 str.format()
:考量可攜性則考慮採用,例如有打算支援不同 linux distrobution 的 Python 套件。- f-string/string literals :強調易讀性時使用。
from string import Template
:強調安全性時使用,例如避免 SQL injection。
語法回顧
Real Python 有篇簡介這幾種用法在語法上的差別,寫得簡單易懂、條理分明。想要複習語法的不妨一讀。
PEP 3101 陳述了除了 %
operator of strings 與 the string Template module 以外,當初為什麼再創造其他種 string formatting 的方式。
str.format
與 f-string
的官方文件則可分別在 string library 與 lexical analysis 的章節中查閱到。
printf-style 使用情境的理由
printf-style 的 %
本質上是一個 operator
,所以在實做與變化上面就會受 operator
本質限制。另外這類相對早期的實做,也有一些沒完全支援(相對新的)資料結構的情況下,所引發的不預期行為。
反過來說也有可能受惠於是 operator
這件事情,例如在某些情境下,比起其他的 string formatting 方式,有一些最佳化效能的好處。例如這篇 logging performance 所陳述的例子[1]。
[1] 感謝 TP 當初幫我 code review 時所分享的案例
跨 distro 的例子
很多 Linux 發布版本( Distribution/Distro )採用 python 作為 glue language ,而該 distro 發行時,通常會綁訂了某個版本的 python 。舉例來說,如果今天有一個套件想要同時支援 Ubuntu 16.04 (預設 python3 版本是 3.5 ) 與 Ubuntu 20.04 (預設 python3 版本是 3.8 ;並且預設「沒有」 python2 )[1],我大概不會想要用 python 3.6 才開始有的 f-string 。
[1] 使用 rmadison 直接查閱各 Ubuntu disto archive 裡對應到的 python3 版本
$ rmadison python3
python3 | 3.2.3-0ubuntu1 | precise | all
python3 | 3.2.3-0ubuntu1.2 | precise-updates | amd64, armel, armhf, i386, powerpc
python3 | 3.4.0-0ubuntu2 | trusty | amd64, arm64, armhf, i386, powerpc, ppc64el
python3 | 3.5.1-3 | xenial | amd64, arm64, armhf, i386, powerpc, ppc64el, s390x
python3 | 3.6.5-3 | bionic | amd64, arm64, armhf, i386, ppc64el, s390x
python3 | 3.6.7-1~18.04 | bionic-updates | amd64, arm64, armhf, i386, ppc64el, s390x
python3 | 3.8.2-0ubuntu2 | focal | amd64, arm64, armhf, i386, ppc64el, riscv64, s390x
python3 | 3.8.6-0ubuntu1 | groovy | amd64, arm64, armhf, i386, ppc64el, riscv64, s390x
python3 | 3.9.4-1 | hirsute | amd64, arm64, armhf, i386, ppc64el, riscv64, s390x
python3 | 3.9.4-1 | impish | amd64, arm64, armhf, i386, ppc64el, riscv64, s390x
你使用 string formatting 的考量是什麼?
There should be one-- and preferably only one --obvious way to do it.
- PEP-20, the Zen of Python
String formatting 或許是 python 中幾個「好像」跟這個概念比較衝突的例子。你選擇的 string formatting 方式,考量又是什麼呢?歡迎與我分享。