PEP 遊行
PEP 遊行
在 Python10 大會上,我以主題演講的形式拉開了開發者日的序幕,演講的結尾部分我稱之為“PEP 遊行”。這是一個對 所有開放 PEP 的簡要概述,其中我對每個 PEP 都表達了高度個人化和主觀的看法。後來我意識到這可能對其他開發者也有興趣。我沒有在會議上做筆記,所以下面是 2002 年 3 月 7 日我一次性花兩小時從頭建立的不同評論集。我打算偶爾用新的評論和新的 PEP 更新它。
—— Guido van Rossum
PEP 42 - 小型功能請求 - Hylton
坦白說,這主要是一個“好主意但優先順序不夠高無法實現”的垃圾場。似乎沒有人會仔細檢視這些想法,找到一個好主意併為此編寫程式碼並提交補丁。因此,實際上,一個被移到 PEP 42 的想法比一個被徹底拒絕的想法更糟糕——它處於一個殭屍區域,無法逃脫到天堂或地獄。我們如何改變這一點?
PEP 206 - 2.0 電池包含 - Zadka
這是一個好主意。但是 PythonLabs 沒有精力推進它,原始作者也沒有。我們如何才能使其成為社群的努力?
PEP 209 - 新增多維陣列 - Barrett, Oliphant
2002 年 3 月 28 日:我之前的評論是基於一些誤解。(例如,新版 Numeric 中的切片與舊版行為相同,並且不像我錯誤地認為的那樣會建立副本。)引用 Perry Greenfield 的話:
[...] 新版本越來越向後相容。事實上,主要區別在於:
- 當標量與陣列組合時的強制轉換規則差異。在科學 Python BoF 會議上,大家一致認為這個改變是件好事。
- 型別由型別物件而不是單字元程式碼表示。我們已將其實現為向後相容,因此應該很少有舊的 Python 程式碼會因此而損壞。
- 對於 2.2 之前的 Python 版本,沒有陣列屬性(即 shape、flat、real 和 imag)(我們使用屬性功能來支援 2.2 及更高版本;因此它僅與舊版 Python 的 Numeric 不相容)
還有一些較小的差異,但這些是 Python 層面主要的向後相容性問題。其中兩個對於大多數使用 Python 2.2 或更高版本的使用者來說應該不是問題。它確實有許多重要的增強功能,但這些不是相容性問題。可能它被接受的最大問題是
- 不相容的 C API。我們可以提供工具使其更容易適應 C 程式碼,但我們無法使其自動化。
- 缺乏庫。我們現在開始記錄 API,提供如何新增 C 程式碼的示例,並新增一些標準庫。在功能達到臨界質量(足以讓人們開始切換,除了天文學領域,這將由我們使用 numarray 的庫驅動)之前,必須有足夠的庫支援(包括繪圖)。
- 小陣列效能較慢。由於它更多地用 Python 編寫,因此對於小陣列(但對於大陣列(> 1MB)則同樣快或更快)來說,速度會慢一個數量級。最佳化在我們的計劃中,但在我們完成庫和安全問題(即將完成)之前不會進行。
- 由於 1) 和 2),目前使用它的人不多(有些人很忙,覺得 Numeric 適合他們的目的;他們需要不僅僅是它的可用性才能嘗試並發表意見)。
[關於併入 Python 核心]
嗯,這仍然是我們的目標,我們正在為此努力(我們甚至開始考慮將文件轉換為 Python 標準)。目前有一個手冊草案。我想社群可能需要一年時間才能顯著地開始使用它(假設我們成功地讓他們這樣做)。
另一方面,我不認為這個時間表應該必然成為決定何時(或是否)將其納入核心的驅動因素。它可以在此之前被納入核心(它們有不同的名稱並且可以共存),也可以在此之後很久。我認為這個決定應該基於一些不同的基礎。
Paul Dubois 給我發郵件支援 Perry 的資訊,宣佈他將很快成為 Numarray 使用者,用於一個特定的應用程式。Paul 還提到 C API 是唯一棘手的問題。他不認為小陣列的效能問題有多大。
根據這些反饋,我預計這個 PEP 將緩慢而穩定地向前發展。我預計作者最終會向我提供一套補丁,將他們的程式碼庫合併到 Python CVS 樹中。這將是針對 Python 2.3 還是更高版本,我無法確定。
PEP 215 - 字串插值 - Yee
我預見這裡的爭論永遠不會得出明確的結論。有些人認為這顯然是 YAGNI(你不需要它)的情況,而另一些人則認為這是初學者程式設計師最重要的缺失功能。我不知道哪一方是對的。即使它是一個需要的功能,語法也存在問題:第一個 $ 在
print $"The area of a $x by $y rectangle is $z"
非常值得商榷,但我看到的任何替代方案(例如 i"...")看起來也不是很好。我們不能總是開啟字面量中的字串插值,因為那會破壞現有程式碼。也許“from __future__ import interpolation”會啟用字串字面量中的插值?(僅限於字面量!)
還有一個問題是是否允許任意表達式,例如
print "The area is ${x*y}"
PEP 216 - Docstring 格式 - Zadka
內容很少。也許應該撤回?還有幾個其他 PEP 處理 doc string,尤其是 256-258,我更喜歡那些。
PEP 228 - 重新設計 Python 的數值模型 - Zadka, van Rossum
這實在是太過於理想化了。有太多未解決的問題,許多甚至在 PEP 中都沒有提及。我認為它應該被拒絕;也許如果將來有興趣,可以成立一個工作組或 SIG 來更深入地探討這個主題。
PEP 237 - 統一長整型和整型 - Zadka, van Rossum
這個已經被接受了,我們應該在 Python 2.3 中實現階段 B1。還需要我多說什麼嗎?
PEP 239 - 為 Python 新增有理數型別 - Zadka
和 228 一樣,我認為這不是一個現實的 PEP,它只是一些開放問題的集合。有理數型別似乎比它解決的問題製造了更多的問題。
也許,**也許**可以使用 C(當然使用 Python 長整型)在擴充套件模組中實現一個高效的有理數型別。但這只是一個努力的問題,似乎沒有人感興趣。同時,如果你需要有理數,純 Python 中有很多實現可用(包括 Demo/classes/Rat.py)。
PEP 240 - 為 Python 新增有理數字面量 - Zadka
鑑於我對 239 的評論,我提議拒絕此項。
PEP 242 - 數值種類 - Dubois
除了作者本人,似乎沒有人有興趣繼續推動這個提案。就我個人而言,我認為這個想法並不特別“Pythonic”——趨勢是減少數值型別,而不是增加(參見 PEP 237)。我相信作者曾表示最好撤回這個 PEP。
PEP 243 - 模組倉庫上傳機制 - Reifschneider
當然,很好,但這應該是一項社群努力。也許 Kapil 的模組倉庫專案 (Gideon, /usr/local/WWW/ftp.python.org/pub/www.python.org/sigs/catalog-sig) 會給它帶來新的生機?
我認為這裡的問題不在於軟體本身,而在於 (a) 建立一個能夠承受整個社群訪問的伺服器(或一組副本),以及 (b) 動員社群將其所有程式碼提交到倉庫。
另一個問題是審查。我認為 CPAN 也未能完全解決這個問題(鑑於我聽到的關於非工作包的抱怨數量)。你如何判斷哪些貢獻是好的?計算下載量?一個“投票支援此包”的表單?
原作者打算怎麼做?
PEP 245 - Python 介面語法 - Pelletier
Jim Fulton 曾表示這個 PEP 過於倉促。我同意。它引入了一個新關鍵字 'interface',我尚未確信這是必需的。另一方面,目前 Zope 中實現此功能的方式也看起來非常醜陋,所以確實可能需要一些東西。我認為將來在對介面的使用有更多經驗時(尤其是在 Zope 3 中),我們會回到這個 PEP,看看我們可以使用多少。也許應該有一個特殊的“凍結”狀態,意味著不拒絕但近期也不予考慮?但其含義應與“空中樓閣”不同——這個 PEP 至少有許多具體的提案並研究了其後果。
PEP 246 - 物件適配 - Evans
直到 Alex Martelli 向我解釋,我才明白這個 PEP 是關於什麼的。我認為它類似於 Zope 3 中的一個操作,它尋找一個給定物件的介面卡,該介面卡實現了給定介面。如果物件本身實現了介面,則返回物件本身;否則系統地搜尋已註冊的介面卡表以找到最合適的介面卡。
但這就是我對這個主題的全部瞭解,我認為它應該保留為一個好主意,直到我們有了一種標準的方式來討論介面。所以我認為這至少會像 PEP 245 一樣具有“凍結”狀態(見上文)。
我必須承認我從未通讀整個 PEP,也從未嘗試閱讀和理解規範或示例實現,所以我可能仍然偏離了方向。
PEP 254 - 讓類看起來更像型別 - van Rossum
這個 PEP 旨在描述經典類實現的變化,使其更接近新式類。我還沒有開始這項工作,而且我認為也許沒有必要——經典類的實現可以保持原樣,直到它在 Python 3000 中被簡單地放棄。在某個時候,當我們認為大多數使用者都在使用新式類時,我們應該為使用舊式類新增警告。PEP 可以用來描述這些警告的時間框架。但在此之前,我們應該首先確保整個標準庫(以及演示和工具)都使用新式類。而這在 Python 2.3 中甚至都不會發生。此外,這可能會破壞子類化特定標準類的使用者程式碼,例如,如果使用者定義了一個依賴強制轉換的子類,而新式類不支援強制轉換。
PEP 256 - 文件字串處理系統框架 - Goodger
PEP 257 - 文件字串約定 - Goodger, van Rossum
PEP 258 - DPS 通用實現細節 - Goodger
我將一併討論這些。我相信 David Goodger 正在做著出色的工作,我仍然經常在 doc-sig 中看到他的帖子。但我完全沒有關注這項工作。由於這不影響語言,只是一種約定,所以我對此並不特別關心。
PEP 262 - 已安裝 Python 包資料庫 - Kuchling
我認為這是一個 distutils 方面的空中樓閣專案吧?也許有人應該直接實現它;我對此沒有任何異議,但我自己並不特別覺得有這個必要。
PEP 263 - 定義 Python 原始碼編碼 - Lemburg
這個已經很接近被合併了。Martin 和 Marc-Andre 正在完善實現。當他們準備好後,我想我就會批准它。有一位外部專家 Stephen Turnbull 提出了一些嚴重的反對意見,他希望我們純粹用 UTF-8 定義語言,並將編碼實現為站點特定的 (?) 鉤子。但沒有人同意他,我自己也回應說我認為最好採用 MAL 的方式。
PEP 265 - 按值排序字典 - Griffin
這是一個對提案者來說非常重要的小想法,但我認為它試圖解決一個最好透過其他方式解決的問題,例如,透過教新手正確的演算法/慣用法。我注意到 PEP 使用了草率的語言,例如,它談論“排序字典”,而字典本身從未被排序——PEP 只是提出了以排序順序返回專案或鍵的方法。
該 PEP 也缺乏明確性:它提出了一系列替代方案,我想我是應該選擇我最喜歡的一個。又讓我成了壞人。:-)
最後,提議的“reversed=<bool>”可選引數似乎完全是應用程式特有的。
我希望拒絕此項,因為它沒有以足夠通用的方式解決足夠普遍的問題,它只會使字典 API 變得混亂。我寧願新增 dict.popitem(key)。
PEP 266 - 最佳化全域性變數/屬性訪問 - Montanaro
PEP 267 - 最佳化模組名稱空間訪問 - Hylton
PEP 280 - 最佳化全域性變數訪問 - van Rossum
這三個應該一起考慮;最多隻能實現其中一個(或者可能是混合體)。我希望最終能實現其中一個,因為我認為它可能帶來巨大的效能優勢:不僅避免了全域性變數和內建函式的字典查詢,而且還能在解析器中識別某些內建函式並生成知道內建函式作用的程式碼,例如 len(x) 的操作碼和“for i in range(x, y, z)”的特殊程式碼。
我認為 Montanaro 的提議過於複雜。我喜歡 Hylton 的版本和我的版本一樣好;他的版本有一些可選功能(例如支援表示“module.attribute”的全域性變數屬性),我認為這些功能不值得增加的複雜性。
在上次 PythonLabs 會議上,我們決定先做一些不那麼雄心勃勃的事情,看看 2.3 之前是否有時間在完成後做更多事情。不那麼雄心勃勃的事情是重構編譯器,使用更合適的抽象解析樹,並引入顯式的多通道。我預測,僅此一項在 2.3 beta1(7 月 17 日)之前所剩的時間裡就幾乎無法完成。
PEP 268 - 擴充套件 HTTP 功能和 WebDAV - Stein
我完全支援這個,但這是庫開發工作,我不會去做。
看來作者已經放棄了,也沒有人接手。有一個實際的原型在 sandbox/Lib 目錄(奇怪的名字)中,來自 2001 年 9 月;也許我們應該催促作者完成工作,或者問他在等什麼。
PEP 269 - Python 的 Pgen 模組 - Riehl
我知道 Martin von Loewis 不喜歡這個(因為它缺乏通用性,例如,除了定義保留字集之外,無法更改詞法分析器),但我認為它可能對那些嘗試使用類似 Python 語言的人(例如,新增新關鍵字和語法 的 Python 預處理器)有所幫助。由於 pgen 與 Python 發行版結合得相當緊密,因此將 pgen 提供給 Python 程式設計師的擴充套件也應該包含在 Python 發行版中,這是有道理的。
所以,我們應該問作者他是否打算實現它。如果不是,它可能應該因為缺乏興趣而被放棄。
PEP 270 - 列表物件的 uniq 方法 - Petrone
與 PEP 265 情況相同。正如關於這個主題的激烈食譜條目所證明的那樣,以完全通用性實現此功能比看起來要困難得多。PEP 未完成:它甚至沒有指定所需的語義!如果作者的實現只有 20 行,為什麼不包含它呢?
我提議拒絕此項,以節省作者的工作(他仍然應該公開他的實現)。
PEP 273 - 從 Zip 檔案匯入模組 - Ahlstrom
我喜歡這個概念。我沒有詳細研究 PEP 或提議的實現,所以不知道它是否總是正確的。我希望它能進入 2.3 版本。
PEP 274 - 字典推導式 - Warsaw
如果我們要採用字典推導式,這個 PEP 已經說清了所有需要說的話。但我甚至不想在 Python 2.3 中考慮這個;我認為這是一個太次要的功能了。
如果有一個以補丁形式存在的有效實現,這將更容易被採納。
有時如果這樣的東西可以用衛生宏或其他型別的預處理器或任何東西來定義,並從模組中匯入,而不是需要對解析器、位元組碼編譯器和虛擬機器進行重大修改,那會很好。
PEP 275 - 多值切換 - Lemburg
我仍然不相信我們需要一個 switch 語句,並且提議的語法存在問題:例如,為什麼只允許常量?為什麼不允許範圍?此外,它提出了許多不同的替代方案而沒有選擇一個。
然而,PEP 提出的第一個替代方案沒有新增任何新語法,只是提議解析器識別某個常見模式併為其生成更好的程式碼。我完全贊成這一點,前提是能夠證明生成的程式碼要麼顯著更快,要麼顯著更小,或兩者兼而有之。在對 PEPs 266、267、280 的評論中提議的編譯器重構之後,這個專案可能會容易得多。
PEP 276 - 整數的簡單迭代器 - Althoff
我犯了一個錯誤,告訴作者我覺得這個太醜了。無論用詞如何,我確實認為它違背了 Pythonic 的原則。對我來說
for i in 12:
print i
看起來不對。也許
for i in len(L):
print i, L[i]
很有吸引力,但我總覺得這不是正確的解決方案。
PEP 277 - Windows NT 的 Unicode 檔名支援 - Hodgson
我不知道這個的狀態,但我相信它已經實現或至少接近實現了?在德國人中是否有爭議?
PEP 278 - 通用換行符支援 - Jansen
我給 Jack 發了一堆“魔鬼代言人”的問題。這個問題是真實存在的,我希望看到它得到解決,但我擔心這太像一個 hack 了。以下是問題列表:
- source() 呼叫到底是什麼?
- 為什麼不支援為輸出檔案設定分隔符?
- 't' 模式與 Windows 上使用此模式顯式呼叫預設文字轉換模式相沖突。
- 為什麼 't' 不能與 '+' 一起使用?據我所知,Windows 上的文字模式支援 '+'。
- 這與 xreadlines 如何互動?與 "for line in file" 如何互動?
- 為什麼滿足於一個預設關閉的編譯時選項?這會帶來問題;開啟它的人會編寫使用 't' 模式的程式碼,然後發現它不可移植。
- 你說 't' 模式被 import 使用。從字串解析原始碼呢?Unicode 字串呢?
- 我認為我需要你澄清關於鎖的評論。如果實現可以被濫用以建立核心轉儲,我不會支援它。
PEP 279 - 增強型生成器 - Hettinger
2002 年 3 月 28 日:作者採納了我的建議,刪除了可重啟迭代器這個想法,我曾在之前的評論中稱之為邪惡。以下是我目前的評論:
- 新的內建函式:indexed()
我喜歡以某種方式並行迭代序列及其索引集的想法。將其作為內建函式很好。
我不喜歡“indexed”這個名字;形容詞不是好的函式名。也許是 iterindexed()?
我不喜歡 start 和 stop 引數。如果我看到這樣的程式碼:
for i, j in iterindexed("abcdefghij", 5, 10): print i, j我期望它會列印5 f 6 g 7 h 8 i 9 j而 PEP 中的規範會列印5 a 6 b 7 c 8 d 9 e非常令人困惑。我建議刪除 start/stop 引數,**或者**將規範更改為
def iterindexed(sequence, start=0, stop=None): i = start while stop is None or i < stop: try: item = sequence[i] except IndexError: break yield (i, item) i += 1這將其有效性僅限於序列(而不是所有可迭代集合),但其優點是 iterindexed(x, i, j) 會迭代 x[i:j],同時報告索引序列 range(i, j)——否則就不那麼容易了。
簡化版本仍然很有吸引力,因為它允許傳入任意迭代器
def iterindexed(collection): i = 0 it = iter(collection) while 1: yield (i, it.next()) i += 1 - 生成器推導式
我認為不值得為此費力。我預計將其植入程式碼生成器需要大量工作:它必須建立一個單獨的程式碼物件才能成為生成器。列表推導式是內聯的,所以我預計生成器推導式程式碼生成器無法與列表推導式程式碼生成器共享太多。而這對於不那麼常見且透過編寫一個兩行輔助函式即可輕鬆完成的事情來說,投資回報率不夠高。
- 生成器異常傳遞
這是 PEP 看起來最薄弱的地方。沒有真正的動機(“這是一個真正的缺陷”不算數 :-)。也沒有暗示應該如何實現。示例中生成器主體有一個“return log”語句,這在目前是非法的,我無法弄清楚這個值會返回到哪裡。這個示例看起來不需要生成器,如果需要,透過設定一個全域性“請停止”標誌並再呼叫一次 next() 很容易停止生成器。(如果你不喜歡全域性變數,可以將生成器設為類的某個方法,並將停止標誌設為例項變數。)
PEP 281 - 使用 range 和 xrange 進行迴圈計數迭代 - Hetland
這是 PEP 212 中 irange() 的替代方案(該 PEP 已被拒絕,但沒有解釋拒絕原因的文字)。只要我們引入 FOO(sequence) 這種表示法,它返回 range(0,len(sequence)) 的(惰性或其他方式的)版本,我認為使用 FOO==range 比其他任何方式都更令人困惑。換句話說,如果非要這樣做,就為它發明一個新名字。
PEP 282 - 日誌系統 - Mick
我要求了這個,但還沒看。不過我已經喜歡它了!希望這個能在 2.3 中實現。
PEP 284 - 整數 for 迴圈 - Eppstein, Ewing
又是一種解決某些人覺得
for i in range(10):
太醜陋的方式。我對此的主要不滿是
for 0 <= i < 10:
將索引變數放在中間,而不是緊跟在 for 關鍵字之後。而在下限是變數的情況下,這對於普通讀者來說會造成困惑
for i <= j < k:
看起來像
for i in j, k:
但在一種情況下,迴圈計數器是 j,在另一種情況下是 i。
這個 PEP 的優點是它引用並評論了所有試圖解決此問題的先前 PEP(204、212、276 和 281)。
我認為當前的解析器生成器將不得不被嚴重濫用才能允許這兩種語法替代方案
for <target_list> in <expression_list>
和
for <expression> <comparison> <target> <comparison> <expression>
因為 <target_list> 可以以 <expression> <comparison> 開頭。
結束語
呼!就這些了。嗯,在廢棄類別中還有幾個 PEP 可能值得評論,但我會等到有人想復活它們。我們應該明確區分被拒絕的 PEP 和延期的 PEP。而且任何被拒絕的 PEP 都不應該沒有拒絕的解釋。
