當前位置:
首頁 > 知識 > 探索Python F-strings是如何工作

探索Python F-strings是如何工作

探索Python F-strings是如何工作

Python部落(python.freelycode.com)組織翻譯,禁止轉載,歡迎轉發。

探索Python F-strings是如何工作

PEP 498 提出一種新型字元串格式化機制,被稱為「字元串插值」或者更常見的一種稱呼是F-strings(主要因為這種字元串的第一個字母是f)。F-strings提供了一種明確且方便的方式將python表達式嵌入到字元串中來進行格式化:

探索Python F-strings是如何工作

同樣的,在F-strings中我們也可以執行函數:

探索Python F-strings是如何工作

F-strings的運行速度很快。比%-string和str.format這兩種格式化方法都快得多——這兩種是最常用的兩種字元串格式化的方式。

探索Python F-strings是如何工作

為什麼F-strings的運行速度這麼快?它們是以怎樣的形式運行得呢?PEP 498給出了如下的線索:

使用最小的語法,F-strings提供了一種在字元串中嵌入表達式的方法。需要注意的是,F-strings是運行過程中形成的表達式,而不是常數值。在Python源代碼中,F-strings是一個以f為前綴,其中包含了表達式的字元串。表達式的結果將顯示在其所在的位置上。

重點是F-strings是運行過程中進行計算的表達式,而不是一個常數值。這意味著F-strings和其他python表達式一樣都是在運行過程中計算出結果的。CPython編譯器在將F-strings解析成字元串和表達式以生成合適的抽象語法樹的階段使性能得到巨大的提升:

探索Python F-strings是如何工作

我們使用ast模塊來查看一個簡單的表達式a + b在F-strings之中和之外兩種情況下的抽象語法樹的情況。可以看到表達式F-strings中的表達式被解析成一個普通的舊式的二進位操作,和單獨的表達式 a + b解析成的結果是一樣的。甚至在位元組碼層面我們也可以看到F-strings表達式也像普通表達式那樣進行計算。

探索Python F-strings是如何工作

add_two函數簡單的將兩個本地變數a和b進行相加並返回結果值。add_two_fstring函數實現的功能類似,但相加的表達式放到f-strings內。在add_two_fstring函數反彙編出的位元組碼中,FORMAT_VALUE指令(這個指令出現在這裡因為畢竟一個F-strings需要將其內部的表達式字元串化),和不使用F-strings的 a + b表達式的結果是一樣的。

F-strings的過程主要分為兩步:一是把花括弧中的表達式計算出來(和普通的Python表達式一樣),然後將其結果填充到花括弧的位置,並將組合後的字元串作為結果返回。這些步驟不需要額外的運行過程處理。這使得F-strings運行速度更快也更有效率。

為何str.format會比F-strings慢得多呢?當看過其對應的反彙編位元組碼之後,原因就很明顯了。

探索Python F-strings是如何工作

反彙編得到的位元組碼中,第一眼就能看到兩個位元組碼指令:LOAD_ATTR 和 CALL_FUNCTION。當我們使用上str.format時,首先要在全局範圍內尋找format函數。這個步驟是通過LOAD_ATTR 指令實現的。全局變數查找是一個開銷比較大的操作,包括了一系列的步驟(如果比較感興趣的話,可以看看我之前關於屬性查找方面的博文)。一旦format函數被定位到,二進位加操作(BINARY_ADD)將會被喚醒對變數a、b進行相加。最後,通過CALL_FUNCTION位元組碼指令調用format函數,然後將格式化後的結果返回。Python中的函數調用具有相當大的開銷。當使用str.format時,消耗在LOAD_ATTR 和 CALL_FUNCTION上額外的時間導致str.format比F-strings慢的多。

那麼%-strings 這種格式化方法又是什麼原因呢?之前的結果可以看到,它的運行速度介於str.format和F-strings之間。讓我們再一次看一下使用%-strings 格式化方法反彙編後的位元組碼來尋找一些線索:

探索Python F-strings是如何工作

一瞬間,我們就發現位元組碼中並沒有LOAD_ATTR 和 CALL_FUNCTION指令——所以 %-string 這種方法避免了全局屬性查找和函數調用的開銷。這解釋了為什麼%-strings 要比str.format快。但為什麼%-strings 的運行速度仍然比f-strings要慢呢?在BINARY_MODULO位元組碼指令上,%-strings 可能會消耗額外的時間。通過分析BINARY_MODULO位元組碼我並沒得出結果,但看了CPython源代碼後,我們就可以了解為什麼在調用BINARY_MODULO時會產生很小的額外開銷。

探索Python F-strings是如何工作

上圖的Python源代碼中可以看出,BINARY_MODULO操作是過載的。每次被調用時,它總需要檢查運算對象的類型來決定元算對象是否為字元串對象(代碼的第7-13行)。如果它們是,然後modulo 執行字元串格式操作。如果不是,它將執行日常的模塊(返回第一個參數和第二個參數的餘數)。儘管很小,但這種類型檢查確實產生了一些額外開銷,而F-strings並不存在這些問題。

希望這篇文章能給大家一些啟發,幫助大家理解為什麼F-strings能從眾多字元串格式化方法中脫穎而出。F-strings快速、易學、實用,能有效減少代碼量,何不快快用起來!


英文原文:https://ogmcsrgk5.qnssl.com/vcdn/1/優質文章長圖/a-closer-look-at-how-python-f-strings-work-f197736b3bdb.png
譯者:mrwoody

喜歡這篇文章嗎?立刻分享出去讓更多人知道吧!

本站內容充實豐富,博大精深,小編精選每日熱門資訊,隨時更新,點擊「搶先收到最新資訊」瀏覽吧!


請您繼續閱讀更多來自 Python部落 的精彩文章:

一个纯python、快速、可扩展的Markdown解释器
月考成绩+NGINX的线程池提升性能9倍!
查看Python代碼性能熱力圖:pyheatmagic
把最小的區塊鏈變大
月考+python高效率代碼實踐:性能,內存和可用性

TAG:Python部落 |

您可能感興趣

Python鏈式操作:PyFunctional
Python中使用Type hinting 和 annotations
為什麼Python如此火?Why Python is so popular?
在Python中使用Elasticsearch
Python之tworoutine
如何將 Scikit-learn Python 庫用於數據科學項目
Bayesian Personalized Ranking 演算法解析及Python實現
Python之Fpgrowth規則探尋
Python Exceptions介紹
Logistic regression 的梯度下降解法-附python實現
Python 標準庫精華: collections.Counter
Python async/await 介紹
Process-Forest-Window進程日誌分析工具;python版的BloodHound
如何用 Python 寫 Alfred Workflow
可以拋棄 Python?Google 開源 Swift for TensorFlow 意味什麼
Python 的 ChatOps 庫:Opsdroid 和 Errbot
使用 Python 和 Prometheus 跟蹤天氣
把Python當作Shell使用:Xonsh
deep-learning-with-python-notebooks中文版
使用PrettyPrinter讓Python輸出更漂亮