一個月前(2月20日),一則新的 PEP 沒有受到任何阻礙就被官方採納了,這麼快的速度,彷佛並很少見。html
然而,更爲高效率的是,僅在半個月內,它的實現就被合入了代碼倉。也就是說,咱們最快有望在 3 天后(3月23日)發佈的 3.9.0 alpha 5 版本中看到它!python
Python 3.9 的發佈計劃:git
這個 PEP 就是 PEP-614:放寬對裝飾器的語法限制。github
當前裝飾器的語法爲:express
decorator: '@' dotted_name [ '(' [arglist] ')' ] NEWLINE
複製代碼
PEP-614 提議將其簡化爲:ide
decorator: '@' namedexpr_test NEWLINE
複製代碼
我已經把 PEP 全文翻譯出來了,Github 地址:dwz.date/RV9測試
放寬對裝飾器的限制,這對以前的用法沒有影響,但至於會帶來哪些新的好處,我還不知道有哪些現實的例子。ui
下面是 PEP 翻譯後的核心內容摘錄,先跟你們一睹爲快吧:idea
--------------摘錄分割線----------------spa
Python 當前要求全部裝飾器都由 dotted name 組成,可選地帶一個調用。本 PEP 提議消除這些限制,並容許任何有效的表達式做爲裝飾器。
(譯註:dotted name,指的是裝飾器在「@」符號後是「xxx」或「xxx.yyy」這種格式。沒有很好地譯法,故未譯。)
在最初引入裝飾器時,Guido表示對其語法做限制是一種偏好,而不是由於技術的要求:
我對此有一種直覺。我不肯定它來自哪裏,但我就是有……所以,儘管未來將語法更改成 @test 至關容易,但我仍想堅持使用更受限的形式,除非給出了真正的使用 @test 會增長可讀性的用例。
儘管在實踐中不多遇到問題,可是多年來,BPO問題和郵件列表帖子不斷出現,要求去除限制。最近的一封郵件(它促成了本提案)提供了一段很好的使用 PyQt5
庫的示例代碼,若是放寬現有的限制,它將變得更具可讀性、地道性和可維護性。
稍做修改的示例:
buttons = [QPushButton(f'Button {i}') for i in range(10)]
# Do stuff with the list of buttons...
@buttons[0].clicked.connect
def spam():
...
@buttons[1].clicked.connect
def eggs():
...
# Do stuff with the list of buttons...
複製代碼
當前,這些裝飾必須重寫成這樣(譯註:上方是假想的最優寫法,但 Python 還不支持,只能用下方的囉嗦寫法):
button_0 = buttons[0]
@button_0.clicked.connect
def spam():
...
button_1 = buttons[1]
@button_1.clicked.connect
def eggs():
...
複製代碼
此外,當前的語法太過寬鬆,以致於沒法將更復雜的裝飾器表達式結合在一塊兒。也就是說,當前的限制並無像預期的那樣去禁止任意複雜的表達式,而是使它們變得更醜陋且效率低下:
# Identity function hack:
def _(x):
return x
@_(buttons[0].clicked.connect)
def spam():
...
# eval hack:
@eval("buttons[1].clicked.connect")
def eggs():
...
複製代碼
在至關長的一段時間內,容許任意有效表達式的決定(而不只僅是放寬當前的限制,如容許取下標),已被視爲裝飾器語法發展的下一個瓜熟蒂落的步驟。正如Guido 在另外一個郵件列表討論中所說:
我以爲強制約束它沒有什麼道理,由於它已再也不是一個普通的表達式。
若對語法進行特殊設置以容許某些有用的用法,只會使當前狀況複雜化,而且幾乎能確定此過程會在未來的某個時間重複。此外,這種語法上的改變的目的之一是阻止使用上述的 eval 和反模式的 identity-function 之類的誘惑。
簡而言之:若是要刪除一些限制,咱們應該刪除全部限制。
在本文檔中,「表達式」一詞的用法與《Python語言參考》中定義的相同。能夠歸納爲「任何在 if、elif 和 while 塊中測試爲有效的內容」。
這與可能更流行的定義稍有不一樣,後者能夠歸納爲「任何做爲有效字符串輸入給 eval 的內容」。
前一個「表達式」的定義更方便,由於它很是貼合咱們的需求,而且能夠重用被現有語言結構所容許的語法。與其它定義相比,它有兩個細微的差別:
這是基於 Guido 在同一封郵件中的洞察。緊接着前面的引述:
可是我不會容許逗號,決不可能同意這樣:
@f, g def pooh(): ... 複製代碼
確實,它可能甚至致使沒有經驗的讀者得出結論,認爲正在使用多個裝飾器,就像它們被堆疊了同樣。這裏要求加括號,可使意圖變得清晰,而無需施加進一步的限制和複雜語法。
在這裏,語法的選擇是明確的。PEP 572解釋了爲何須要在頂級表達式語句的周圍加上括號:
加入此規則是爲了簡化用戶在賦值語句和賦值表達式之間的選擇——沒有令二者都生效的語法位置。
因爲賦值語句在此處無效,所以賦值表達式就沒必要帶括號。
(譯註:賦值表達式,即 Assignment Expressions 或 Named Expressions,是 Python 3.8 引入的新特性,就是它引入了新的「:=」海象操做符。)
-----------------正文分割線---------------
PEP 的全文翻譯已收錄在 Github 的《PEP中文翻譯計劃》中,目前已有 20+ 篇 PEP 翻譯,歡迎感興趣的同窗查閱&參與翻譯。
附錄:
PEP614英文:www.python.org/dev/peps/pe…
PEP614中文:dwz.date/RV9
PEP中文翻譯計劃:github.com/chinesehuaz…