神奇的 f-strings(Python)
在以前的文章我曾經說過,如果學習和在實際生產環境使用 Python 3,版本至少應該從Python3.6開始,版本越高越好。現在是已經是Python 3.7,按計劃Python 3.8今年10月20日也會發布。
為什麼我要強調從 Python 3.6開始呢?我認為在這之前的版本無論是效能和語法完整性都不夠,在Python 3.6時添加了非同步生成器、非同步推導語法,非常實用的Path模組等等,另外一個很重要的是添加了f-strings語法,大家用了就會發現根本停不下來。本文就和大家聊聊這個神奇的 f-strings。
f-string是格式化字串的新語法。與其他格式化方式相比,它們不僅更易讀,更簡潔,不易出錯,而且速度更快!我們首先了解下視覺化字串語法的歷史
1: %-formatting
最早的格式化是用%(百分號), 它這麼用:
%符號前面使用一個字串作為模板,模板中有標記格式的佔位符號。佔位符控制著顯示的格式,這裡用的%s
表示格式化成字串,另外常用的是%d
(十進位制整數)、%f
(浮點數)。
格式化語法也可以格式化多個變數,需要把變數用括號括起來:
另外也支援使用字典的形式:
這種用法一直到現在仍然被使廣泛使用,但是其實它是一種不被提倡使用的語法(我初Python學習時,
2. str.format()
從 Python 2.6開始,新增了一種格式化字串的函式str.format()
,基本語法是通過{}
和:
來代替以前的%
。format函式支援通過位置、關鍵字、物件屬性和下標等多種方式使用,不僅引數可以不按順序,也可以不用引數或者一個引數使用多次。並且可以通過對要轉換為字串的物件的__format __
方法進行擴充套件。
通過位置訪問:
通過關鍵字訪問:
通過物件屬性訪問:
通過下標訪問:
可以感受到format函式極大的擴充套件了格式化功能。但是當處理多個引數和更長的字串時,str.format() 的內容仍然可能非常冗長,除了定義引數變數,需要把這些變數寫進format方法裡面。
3. f-Strings
現在好了,Python 3.6新增了f-strings,這個特性叫做字面量格式化字串
,F字串是開頭有一個f的字串文字,Python會計算其中的用大括號包起來的表示式,並將計算後的值替換進去。
如果你學過Ruby,ES6,你會非常容易接受這樣的語法。另外在速度上,f-strings是三種方案中最快的:
可以側面感受到,str.format最慢,%s的稍快一點,F-string是最快的!你還有什麼利用不用它?
現在我寫Python 3.6以上的程式碼時,我已經完全不用另外2種格式化用法了。
future-fstrings
通過上面的例子,希望我們有一個共識,就是如果你的專案或者工作中使用的Python版本已經不小於3.6,f-string格式化是首選方式,不僅在保持功能強大的同時語義上更容易理解,而且效能也有較大的提升。但是不巧你用不了Python的f-strings,還有個選擇,就是 future-fstrings 這個專案。它的作者也是pre-commit作者,一個pytest和tox核心開發。
在我個人電腦的Python 2.7 版本上體驗一下:
是不是很酷?這個庫的原理值得大家借鑑,我詳細的分析下。
為什麼根本沒有import future_fstrings 程式碼卻能正常執行?
這是因為在你安裝future_fstrings這個包時,在 site-packages 下新增一個叫做aaaaa_future_fstrings.pth
的檔案。pth檔案是路徑配置檔案,這種檔案本來是為了擴充搜尋模組路徑進sys.path的,也有一些包用它做高階定製。
我們這裡提aaaaa_future_fstrings.pth
在這裡被用來匯入包了。所以CPython直譯器執行時會載入這個pth檔案,然後呼叫其中的future_fstrings.register
方法。
emmm, pth檔案很多同學感覺很陌生,其他它離我們很近,只是作為開發者日常基本不需要關注它。舉一個最常見的例子easy-install.pth
。有時候為了開發方便,安裝包的時候是這樣用的:
這樣你使用的aiomcache,是你本地的版本:
這樣怎麼生效的呢?有些同學會說「嗯,安裝後就放入了site-packages下了唄」,其實不然,你去系統Site包目錄下是找不到,但是呢,sys.path是可以找到的:
可以看到,搜尋的目錄包含了/Users/dongweiming/aiomcache
,所以能找到。這是怎麼生效的呢?其實就是靠上面說的easy-install.pth
:
看到了吧,所以說 pth配置檔案擴充了要搜尋模組的路徑。我們測試下把aiomcache這樣刪掉:
再import,和檢視搜尋目錄就找不到aiomcache 了:
這個包實現f-strings的原理是?
奧妙就在# coding: future_fstrings
這一句中,另外一個寫法是# -*- coding: future_fstrings -*-
。
想必大家會想到Python 2裡面的# coding: utf-8
頭了吧,這句註釋用來宣告檔案編碼。這個包巧妙的利用了它, 在呼叫register函式時給 codecs 模組註冊了新的檔案編碼方式,在詞法掃描時把f-strings轉換成format的寫法,上面的例子等價於:
不過這樣的實現效能肯定比原生的要差很多。大家有興趣的可以嚐個鮮兒~
結束語
在 Python 之禪中有這麼一句:
也就是「應該提供一種,且最好只提供一種,一目瞭然的解決方案」。雖然f-strings不是唯一可能的格式化字串選擇,但它是最好最正確的那個選擇!!!