今天我們推薦一個名為specialist的library,並試著了解Python3.12的f-strings in the grammar。有關於Python3.12的更新可以參考What’s New In Python 3.12或是Real Python的摘要。這次更新最令我們開心的小功能是,pathlib終於有了path.walk,省去了當要列出所有資料夾及檔案時,需要呼叫os.walk的窘境。
Python3.11相比於3.10,執行速度提高不少,有很大原因是因為微軟的Fast CPython Team,做了許多最佳化。詳細的內容可以參考PEP 659 – Specializing Adaptive Interpreter及TalkPython
的381集-Python Perf: Specializing, Adaptive Interpreter和388集-Python 3.11 is here and it's fast。
我們特別推薦大家看看specialist這個由Fast CPython Team的成員Brandt Bucher所維護的library。specialist會用不同顏色,來標注程式中還有機會可以提升速度的地方。
說明文件中舉了一個淺顯易懂的攝式與華式溫度轉換的例子,下面是我們一般會寫出的程式。
下面是經過specialist建議所修改的程式。只需要將int改為float(32->32.0)及將5/9和9/5加上括號,即可以提升速度。
我們建議大家可以按照自己習慣的方式來寫code,等到大部份的邏輯寫好後,再使用specialist來幫忙看看有沒有可以改進的地方。
如果想快速了解Python3.11~Python3.12速度提升的關鍵,可以觀看Brandt Bucher於PyCon US 2023的演講,裡面也有稍微提到specialist。
PEP-701 Syntactic formalization of f-strings中,說明了這個變更,將可以大幅降低維護的難度,並讓f-strings的parser符合official Python grammar。比較有趣的是PEP-701於2022-11-15提出,馬上就被接受並導入在Python3.12中,這開發速度著實有點驚人。因為Python3.12除了繼續使用各種策略進行速度提升外,也花費不少精力在放寬Gil的限制。
在Python3.11以前,四種表示str型態的符號,包括'、"、'''及"""在同一個f-string中只能使用一次,不能nested,所以最極限的f-string寫法會像是:
#python3.11
>>> f"""{f'''{f'{f"{1+1}"}'}'''}"""
2
但在Python3.12,我們可以:
#python3.12
>>> f"{f"{f"{f"{f"{f"{1+1}"}"}"}"}"}"
'2'
另外,這個變動讓我們可以在f-string中,重複使用同一種str型態的符號。
>>> songs = ['Take me back to Eden', 'Alkaline', 'Ascensionism']
#python3.11
>>> f"This is the playlist: {', '.join(songs)}"
'This is the playlist: Take me back to Eden, Alkaline, Ascensionism'
#python3.12
>>> f"This is the playlist: {", ".join(songs)}"
'This is the playlist: Take me back to Eden, Alkaline, Ascensionism'
可以使用Multi-line expression及加入comment。
#python3.12
>>> f"This is the playlist: {", ".join([
... 'Take me back to Eden', # My, my, those eyes like fire
... 'Alkaline', # Not acid nor alkaline
... 'Ascensionism' # Take to the broken skies at last
... ])}"
'This is the playlist: Take me back to Eden, Alkaline, Ascensionism'
可以使用Backslash。所以可以在f-string內直接使用像'\n'或'\t'等符號來連接str。此外,也會連帶影響unicode escape sequence。
#python3.12
>>> print(f"This is the playlist: {"\n".join(songs)}")
This is the playlist: Take me back to Eden
Alkaline
Ascensionism
>>> print(f"This is the playlist: {"\N{BLACK HEART SUIT}".join(songs)}")
This is the playlist: Take me back to Eden♥Alkaline♥Ascensionism
自從f-string於Python3.6導入之後,一直都是它的愛用者。此次的變更,個人覺得不太習慣,感覺很不pythonic,可能得花些時間才能適應。因為綜合這三個特點來看,「好像」是在鼓勵我們於f-string中進行較冗長或是nested的操作,且因為quote可以重覆使用,在沒有IDE顏色的提示下,我很懷疑自己是否能看得懂程式碼。但是從pep-701的討論中,可以看出開發者認為利遠大於弊,或許身為Python使用者的我們,得順應發展做出改變才是。
非常開心又完成一次充實的鐵人挑戰賽,請容我們用些許篇幅,感謝幫助我們完賽的兩位功臣。
Markdown線上編輯平台HackMD。本系列文的所有編輯皆是在HackMD上完成,於發文前再直接貼過來,由衷感謝他們開發了這個好用的平台。如果有同好想交流Python的原理或知識,可以透過LinkedIn或E-mail 聯絡我。