Python 字串格式化

LynnShaw發表於2016-06-09

對於一種語言,我們主張關注於用一種合適的方法來處理大部分的情況,Python字串格式化卻是一個另類,而且其越來越多樣化。從 Python 3.6 開始我們有三種字串格式化的方式(除了簡單的連線或使用 string.Template):

  • 使用%操作符
  • str.format
  • 插入字串

(如果你不想主動閱讀所有的這些,我會在PyGraz meetup in February 2016裡給你一個關於這個稍微擴充套件的閃電式演講,裡面會有更多一點的例子)

%-formatting

%-formatting從1.0版本開始就成為語言的一部分了。如果你用過Python3之前的版本,你會知道這個。

這個或多或少的有點像C語言的 sprintf 。它會起作用,但是使用起來有點複雜。

因為它只支援有限的型別,所以在傳值到字串格式化器之前,你得把你的自定義物件轉換成它支援的型別之一。

很多年後,本地字串資料型別擴充套件了一種 format 方法:

str.format()

在2008年10月被新增進Python2.6,類似於上下文管理器。在PEP-3101有詳細描述,它著力於解決老的二元操作符%的一些不足,比如只支援有限的型別,以及在實際處理整個表示式右半部分的時候,會出現一些容易導致錯誤特殊的情況。

由於 .format 是一個方法而不是操作符(被對映到一個二元函式),處理引數會更加明確。如果你傳入一個字串,它就會被解釋為一個字串。如果你傳入只包含一個字串的元組,那它就被解釋為只包含一個字串的元組。

對比與%操作符,它還支援使用命名引數而不需要字典。

起初,它的發明是為了完全取代%操作符(它被計劃用來反對Python 3.1的老式格式化功能)但是並沒有完全發生。這個字串格式化器的核心功能基本是和老的%操作符一樣的,但語法略有不同,恕我直言更為直觀一些。實際上,因為Ulrich和我建立了pyformat.info來幫助人們遷移到新系統。

但是,很顯然,pep – 3101並沒有停留在只是清理舊的特性。它還引入了一個協議,允許使用有更多樣化互動的自定義類:

你可以想象對於字串格式化 __format__ 方法像 __str__ 一樣你可以傳遞選擇項。如果你在你的物件中有 __format__ 方法,當你使用格式化方法時它就會代替 __str__ (除非你做些什麼比如 "{!s}".format(country)")。

事實上你會在 datetime.date class in Python 3.4找到一個關於如何使用的很好的例子:

這允許你使用“parent”字串格式直接來格式化日期,這樣就不需要首先把你的日期物件轉換成一個字串,然後再傳遞到字串格式化器中:

PEP-0498: 字串插入

這是現在推薦的字串格式化方法,.format 太繁瑣了:

PEP-0498致力於通過提供一些在別的語言比如Ruby,Scala,Perl中常見且存在一段時間的東西:字串插入,來改善這種情況。這裡表示式可以直接被整合到字串,這意味著你不必再顯式地呼叫任何額外的函式。

ES2015最近將這個特性引入到了JavaScript中,它被稱為“模板字串”:

因為Python 3.0的一點歷史問題,引號在Python中並不可用。再次引入也會再次影響到語言的基本語法。相代替的,另一個字串字首被引入: f.

你不再需要對一個字串顯式地呼叫 .format() 方法了,只是簡單地用 f字首標記一下格式以及內聯最終字串中你想要包括的表示式。否則它們就會提供和 .format()相同的功能。這些格式化字串在文件中也被稱為“f-strings”。

這看起來確實十分美好,但因為python 3.6會在12個月後才能夠釋出,你恐怕還要等上一段時間。話雖這麼說,程式碼卻已經在那兒了,所以你能做的就是獲取一個python 3.6預釋出版本或者使用一些像 pyenv 的小訣竅,然後讓它執行就行了。

其實還有很多,這裡有其他的PEP(0501),它想要引入i-strings,而這類字串導致了字串的懶惰計算,以至於例如你能在最終評估之前能做一些國際化(i18n)或者安全檢查。雖然這個提案已延緩至進一步的討論,但這看起來是個很好的想法。

但是回到f-strings:如果你想知道更多關於字串插入的解決方案,看看PEP-0502 ,它包括一個關於背後的動機和來自其他語言特性靈感的詳細討論。

相關文章