
作者:豌豆花下貓
來源:Python貓
花下貓語:前兩天,我偶然在一個知識星球(劉欣老師的“碼農(nóng)翻身”)里看到一篇主題,劉老師表示 python 的類方法非要帶個 self,而不像其它語言那樣隱藏起來,這讓人很不爽。我對此也有同感。在經(jīng)過群聊討論后,我獲知 Guido 曾經(jīng)專門撰文解釋過這個問題。這篇文章并不好懂,我抽空先翻譯出來了,看看能收到什么回應(yīng)。如果可能的話,后續(xù)再另寫文章分析。
布魯斯·??藸枺˙ruce Eckel)發(fā)了篇博文[1],提議從類方法的形參列表中刪除“self”。我將解釋為什么這個提議不能通過。(譯注:Bruce 是《Thinking in Java》、《Thinking in C++》等多本書籍的作者,也是個 Python 開發(fā)者。他的文章總結(jié)了當(dāng)年在巴西 Pycon 上的一次討論,主要觀點(diǎn)是在定義類方法時,形參中的“self”是多余的,而且由它引發(fā)的報錯信息具有一定的誤導(dǎo)性。)
Bruce 的提議
Bruce 知道,我們需要一種方法來區(qū)分對實(shí)例變量的引用和對其它變量的引用,因此他建議將“self”設(shè)為關(guān)鍵字。
考慮一種典型的類,它有一個方法,例如:
class C: def meth(self, arg): self.val = arg return self.val
跟據(jù)Bruce 的提議,這將變?yōu)椋?
class C: def meth(arg): # Look ma, no self! self.val = arg return self.val
這樣每個方法會節(jié)省 6 個字符。但我不覺得 Bruce 提出這個建議是為了減少打字。
我認(rèn)為他真正關(guān)心的是程序員(可能來自其它語言)所浪費(fèi)的時間,有時候似乎不需要指定“self”參數(shù),而且他們偶爾忘記了要加(即使他們十分清楚——習(xí)慣是一種強(qiáng)大的力量)。確實(shí),與忘記在實(shí)例變量或方法引用之前鍵入“self.”相比,從參數(shù)列表中省略“self”,往往會導(dǎo)致很模糊的錯誤消息。
也許更糟糕的是(如 Bruce 所述),當(dāng)正確地聲明了方法,但是在調(diào)用時的參數(shù)數(shù)量不對,這時收到的錯誤消息。如 Bruce 給出的以下示例:
Traceback (most recent call last): File "classes.py", line 9, in obj.m2(1) TypeError: m2() takes exactly 3 arguments (2 given)
我贊同它是令人困惑的,但是我寧愿去解決此錯誤消息,而不是修改語言。
為什么 Bruce 的提議不可行
首先,讓我提出一些與 Bruce 的提議相反的典型論點(diǎn)。
這有一個很好的論據(jù)可以證明,在參數(shù)列表中使用顯式的“self”,可以增強(qiáng)以下兩種調(diào)用方法在理論上的等效性。假設(shè)“ foo”是“C”的一個實(shí)例:
foo.meth(arg) == C.meth(foo, arg)
(譯注:說實(shí)話,我沒有理解這個例子的意思。以下僅是個人看法。在類的內(nèi)部定義方法時,可能會產(chǎn)生幾種不同的方法:實(shí)例方法、類方法和 靜態(tài)方法。它們的作用和行為是不同的,那么在定義和調(diào)用時怎么做區(qū)分呢?Python 約定了一種方式,即在定義時用第一個參數(shù)作區(qū)分:self 表示實(shí)例方法、cls或其它符號 表示類方法……三種方法都可以被類的實(shí)例調(diào)用,而且看起來一模一樣,如上例的等號左側(cè)那樣。這時候就要靠定義時賦予的參數(shù)來區(qū)分了,像上例等號右側(cè),第一個參數(shù)是實(shí)例對象,表明此處是個實(shí)例方法。)
另一個論據(jù)是,在參數(shù)列表中使用顯式的“self”,將一個函數(shù)插入一個類,獲得動態(tài)地修改一個類的能力,創(chuàng)建出相應(yīng)的一個類方法。
例如,我們可以創(chuàng)建一個與上面的“C”完全等效的類,如下所示:
# Define an empty class: class C: pass # Define a global function: def meth(myself, arg): myself.val = arg return myself.val # Poke the method into the class: C.meth = meth
請注意,我將“self”參數(shù)重命名為“myself”,以強(qiáng)調(diào)(在語法上)我們不是在此處定義一個方法(譯注:類外部的是函數(shù),即 function,類內(nèi)部的是方法,即 method)。
這樣之后,C 的實(shí)例就具有了一個“meth”方法,該方法有一個參數(shù),且功能跟之前的完全一樣。對于在把方法插入類之前就創(chuàng)建的那些 C 的實(shí)例,它甚至也適用。
我想 Bruce 并不特別在意前述的等效性。我同意這只是理論上的重要。我能想到的唯一例外是舊式的調(diào)用超級方法的習(xí)語(idiom)。但是,這個習(xí)語很容易出錯(正是由于需要顯式地傳遞"self"的原因),這就是為什么在 Python 3000中,我建議在所有情況下都使用"super()"的原因。
Bruce 可能會想到一種使第二個等效例子起作用的方法——在某些情況下,這種等效性真的很重要。我不知道 Bruce 花了多少時間思考如何實(shí)現(xiàn)他的提議,但是我想他正在考慮將一個名為“self”的額外形參自動地添加到直接地在類內(nèi)部定義的所有方法的思路(我必須說是“直接地”,以便那些嵌套在方法內(nèi)部的函數(shù),能免于這種自動操作)。這樣,可以使第一個等效例子保持等效。
但是,有一種情況我認(rèn)為 Bruce 不能在不向編譯器中添加某種 ESP 的情況下解決:裝飾器。我相信這是 Bruce 的提議的最終敗筆。
當(dāng)裝飾一個方法時,我們不知道是否要自動地給它加一個“self”參數(shù):裝飾器可以將函數(shù)變成一個靜態(tài)方法(沒有“self”)或一個類方法(有一個有趣的 self,它指向一個類而不是一個實(shí)例),或者可以做一些完全不同的事情(用純 Python 實(shí)現(xiàn)“ @classmethod”或“ @staticmethod”的裝飾器是繁瑣的)。除非知道裝飾器的用途,否則沒有其它辦法來確定是否要賦予正在定義的方法一個隱式的“self”參數(shù)。
我拒絕諸如特殊包裝的“@classmethod”和“@staticmethod”之類的黑科技。我也認(rèn)為除了自檢外,自動地確定某個方法是類方法(class method)、實(shí)例方法(instance method)還是靜態(tài)方法(static method),這不是一個好主意(就像在 Bruce 的文章的評論中,有人建議的那樣):這使得很難僅僅根據(jù)方法前的“def”,來決定應(yīng)該怎樣調(diào)用該方法。
(譯注:對于一個方法,在當(dāng)前的添加了相應(yīng)參數(shù)的情況下,可以簡單地加裝飾器,區(qū)分它是哪種方法,調(diào)用時也容易區(qū)分調(diào)用;但是,如果沒有加參數(shù),即使可以用神奇的自動機(jī)制來區(qū)分出它是哪種方法,但在調(diào)用時,你不好確定該怎么調(diào)用)。
在評論中,我看到了一些非常極端的對 Bruce 的提議的附和,但通常的代價是使得規(guī)則難以遵循,或者要求對語言進(jìn)行更深層的修改,這令我們極其難以接受它,特別是合入 Python 3.1。順便說一句,對于 3.1,再次聲明我們的規(guī)則,新特性只有在保持向后兼容的情況下才是可接受的。
有一個似乎可行的建議(可以使它向后兼容)是把類中的
def foo(self, arg): ...
改成這樣的語法糖:
def self.foo(arg): ...
但我不認(rèn)同它把“self”變?yōu)楸A糇郑╮eserved word),或者要求前綴必須是“self”。如果這樣做了,那對于類方法,很容易也出現(xiàn)這種情況:
@classmethod def cls.foo(arg): ...
好了,相比于現(xiàn)狀,我并沒有更喜歡這個。但是相比于 Bruce 的提議或在他的博客評論區(qū)中提出的更極端的說法,我認(rèn)為這個要好得多,而且它具有向后兼容的巨大優(yōu)勢,并且不需要很費(fèi)力,就可以寫成帶有參考實(shí)現(xiàn)的 PEP。(我想 Bruce 應(yīng)該會發(fā)現(xiàn)自己提案中的缺陷,如果他真的付出努力嘗試編寫可靠的 PEP 或者嘗試實(shí)現(xiàn)它。)
我可以繼續(xù)聊很多,但這是一個陽光明媚的周日早晨,而我還有其它的計劃... :-)
作者:Guido van Rossum,寫于:2008.10.26
參考資料
[1] Bruce博文:http://www.artima.com/weblogs/viewpost.jsp?thread=239003
[2] Guido原文: https://neopythonic.blogspot.com/2008/10/why-explicit-self-has-to-stay.html
——熱門課程推薦:
想學(xué)習(xí)PYTHON數(shù)據(jù)分析與金融數(shù)字化轉(zhuǎn)型精英訓(xùn)練營,您可以點(diǎn)擊>>>“人才轉(zhuǎn)型”了解課程詳情;
想從事業(yè)務(wù)型數(shù)據(jù)分析師,您可以點(diǎn)擊>>>“數(shù)據(jù)分析師”了解課程詳情;
想從事大數(shù)據(jù)分析師,您可以點(diǎn)擊>>>“大數(shù)據(jù)就業(yè)”了解課程詳情;
想成為人工智能工程師,您可以點(diǎn)擊>>>“人工智能就業(yè)”了解課程詳情;
想了解Python數(shù)據(jù)分析,您可以點(diǎn)擊>>>“Python數(shù)據(jù)分析師”了解課程詳情;
想咨詢互聯(lián)網(wǎng)運(yùn)營,你可以點(diǎn)擊>>>“互聯(lián)網(wǎng)運(yùn)營就業(yè)班”了解課程詳情;
數(shù)據(jù)分析咨詢請掃描二維碼
若不方便掃碼,搜微信號:CDAshujufenxi
LSTM 模型輸入長度選擇技巧:提升序列建模效能的關(guān)鍵? 在循環(huán)神經(jīng)網(wǎng)絡(luò)(RNN)家族中,長短期記憶網(wǎng)絡(luò)(LSTM)憑借其解決長序列 ...
2025-07-11CDA 數(shù)據(jù)分析師報考條件詳解與準(zhǔn)備指南? ? 在數(shù)據(jù)驅(qū)動決策的時代浪潮下,CDA 數(shù)據(jù)分析師認(rèn)證愈發(fā)受到矚目,成為眾多有志投身數(shù) ...
2025-07-11數(shù)據(jù)透視表中兩列相乘合計的實(shí)用指南? 在數(shù)據(jù)分析的日常工作中,數(shù)據(jù)透視表憑借其強(qiáng)大的數(shù)據(jù)匯總和分析功能,成為了 Excel 用戶 ...
2025-07-11尊敬的考生: 您好! 我們誠摯通知您,CDA Level I和 Level II考試大綱將于 2025年7月25日 實(shí)施重大更新。 此次更新旨在確保認(rèn) ...
2025-07-10BI 大數(shù)據(jù)分析師:連接數(shù)據(jù)與業(yè)務(wù)的價值轉(zhuǎn)化者? ? 在大數(shù)據(jù)與商業(yè)智能(Business Intelligence,簡稱 BI)深度融合的時代,BI ...
2025-07-10SQL 在預(yù)測分析中的應(yīng)用:從數(shù)據(jù)查詢到趨勢預(yù)判? ? 在數(shù)據(jù)驅(qū)動決策的時代,預(yù)測分析作為挖掘數(shù)據(jù)潛在價值的核心手段,正被廣泛 ...
2025-07-10數(shù)據(jù)查詢結(jié)束后:分析師的收尾工作與價值深化? ? 在數(shù)據(jù)分析的全流程中,“query end”(查詢結(jié)束)并非工作的終點(diǎn),而是將數(shù) ...
2025-07-10CDA 數(shù)據(jù)分析師考試:從報考到取證的全攻略? 在數(shù)字經(jīng)濟(jì)蓬勃發(fā)展的今天,數(shù)據(jù)分析師已成為各行業(yè)爭搶的核心人才,而 CDA(Certi ...
2025-07-09【CDA干貨】單樣本趨勢性檢驗:捕捉數(shù)據(jù)背后的時間軌跡? 在數(shù)據(jù)分析的版圖中,單樣本趨勢性檢驗如同一位耐心的偵探,專注于從單 ...
2025-07-09year_month數(shù)據(jù)類型:時間維度的精準(zhǔn)切片? ? 在數(shù)據(jù)的世界里,時間是最不可或缺的維度之一,而year_month數(shù)據(jù)類型就像一把精準(zhǔn) ...
2025-07-09CDA 備考干貨:Python 在數(shù)據(jù)分析中的核心應(yīng)用與實(shí)戰(zhàn)技巧? ? 在 CDA 數(shù)據(jù)分析師認(rèn)證考試中,Python 作為數(shù)據(jù)處理與分析的核心 ...
2025-07-08SPSS 中的 Mann-Kendall 檢驗:數(shù)據(jù)趨勢與突變分析的有力工具? ? ? 在數(shù)據(jù)分析的廣袤領(lǐng)域中,準(zhǔn)確捕捉數(shù)據(jù)的趨勢變化以及識別 ...
2025-07-08備戰(zhàn) CDA 數(shù)據(jù)分析師考試:需要多久?如何規(guī)劃? CDA(Certified Data Analyst)數(shù)據(jù)分析師認(rèn)證作為國內(nèi)權(quán)威的數(shù)據(jù)分析能力認(rèn)證 ...
2025-07-08LSTM 輸出不確定的成因、影響與應(yīng)對策略? 長短期記憶網(wǎng)絡(luò)(LSTM)作為循環(huán)神經(jīng)網(wǎng)絡(luò)(RNN)的一種變體,憑借獨(dú)特的門控機(jī)制,在 ...
2025-07-07統(tǒng)計學(xué)方法在市場調(diào)研數(shù)據(jù)中的深度應(yīng)用? 市場調(diào)研是企業(yè)洞察市場動態(tài)、了解消費(fèi)者需求的重要途徑,而統(tǒng)計學(xué)方法則是市場調(diào)研數(shù) ...
2025-07-07CDA數(shù)據(jù)分析師證書考試全攻略? 在數(shù)字化浪潮席卷全球的當(dāng)下,數(shù)據(jù)已成為企業(yè)決策、行業(yè)發(fā)展的核心驅(qū)動力,數(shù)據(jù)分析師也因此成為 ...
2025-07-07剖析 CDA 數(shù)據(jù)分析師考試題型:解鎖高效備考與答題策略? CDA(Certified Data Analyst)數(shù)據(jù)分析師考試作為衡量數(shù)據(jù)專業(yè)能力的 ...
2025-07-04SQL Server 字符串截取轉(zhuǎn)日期:解鎖數(shù)據(jù)處理的關(guān)鍵技能? 在數(shù)據(jù)處理與分析工作中,數(shù)據(jù)格式的規(guī)范性是保證后續(xù)分析準(zhǔn)確性的基礎(chǔ) ...
2025-07-04CDA 數(shù)據(jù)分析師視角:從數(shù)據(jù)迷霧中探尋商業(yè)真相? 在數(shù)字化浪潮席卷全球的今天,數(shù)據(jù)已成為企業(yè)決策的核心驅(qū)動力,CDA(Certifie ...
2025-07-04CDA 數(shù)據(jù)分析師:開啟數(shù)據(jù)職業(yè)發(fā)展新征程? ? 在數(shù)據(jù)成為核心生產(chǎn)要素的今天,數(shù)據(jù)分析師的職業(yè)價值愈發(fā)凸顯。CDA(Certified D ...
2025-07-03