Python的這種設(shè)計(jì)是作者從Modula-3中借鑒來的啼县,在后面使用的情況看來材原,這個(gè)設(shè)計(jì)也是比較成功的。我們對比Python和C++討論一下這個(gè)問題:
Modula-3是上世紀(jì)80年代末數(shù)字設(shè)備公司(DEC)系統(tǒng)研究中心(SRC)和Olivetti研究中心(ORC)設(shè)計(jì)的一門語言季眷。盡管這門語言沒有在業(yè)界廣泛的應(yīng)用起來余蟹,但這么語言對后面被發(fā)明的Java, Python, Caml, C# 都產(chǎn)生了很多的影響
首先,調(diào)用的時(shí)候要求指定"this"子刮,讓我們更明確的區(qū)分調(diào)用的是一個(gè)成員變量威酒、函數(shù)或者是一個(gè)局部變量、函數(shù)挺峡。當(dāng)我們讀到self.x或者self.meth()葵孤,即使我們不知道class的定義也能100%確定這里調(diào)用的是一個(gè)成員變量或者方法。我們設(shè)想一下橱赠,在C++中尤仍,我們還可以通過查看并排除所有的局部變量的方式去確認(rèn)變量是成員變量(假設(shè)全局變量很少見,即使出現(xiàn)也是"g_"這種很容易辨認(rèn)的)狭姨。而在Python中宰啦,由于變量不需要額外的定義,這個(gè)辦法就失效了饼拍,唯一的辦法就只有看class的定義赡模,所以this就成了必須的。 很多C++和Java的編碼規(guī)范中會(huì)規(guī)定成員函數(shù)或變量要有m_前綴师抄,我們也可以看到這種編碼規(guī)范是十分必要的漓柑。
其次,由于this這個(gè)對當(dāng)前實(shí)例的強(qiáng)制顯式引用叨吮,Python不需要引入任何新的語法就可以引用或者調(diào)用其它類(包括父類)的成員變量和函數(shù)辆布。在C++中,如果我們想要在子類中調(diào)用父類的函數(shù)挤安,我們需要用到::這個(gè)運(yùn)算符谚殊;在Python中我們這么寫baseclass.methodname(self, <argument list>)。Python的這種語法在實(shí)現(xiàn)子類的init()時(shí)特別有用蛤铜,例如我們經(jīng)常需要在子類中override父類的函數(shù)并且調(diào)用父類函數(shù)自身。
最后丛肢,就是性能上的些許考量:在Python的語言定義中围肥,局部變量就是在函數(shù)體中賦值,并且沒有在全局顯式的聲明過的變量蜂怎。當(dāng)然在語言設(shè)計(jì)上穆刻,我們有很多的辦法去告訴解釋器、編譯器某個(gè)變量賦值是針對一個(gè)局部變量還是一個(gè)成員變量杠步,但出于解釋性語言的性能考慮氢伟,最好是語義上的的規(guī)定榜轿。C++用變量必須顯示的聲明解決了這個(gè)問題,但Python沒有額外的變量聲明語法朵锣,如果僅僅是出于上面所說的目的引入類似C++的變量必須顯式的聲明就顯得太得不償失了谬盐。所以,self.var這種語法就是一個(gè)非常優(yōu)美的解決方案诚些。我們在函數(shù)里寫上self.var這種語法飞傀,解釋器就不用費(fèi)力地在全局范圍內(nèi)進(jìn)行變量的查找。換句話說诬烹,局部變量和成員變量存在于兩個(gè)不同的命名空間砸烦,我們需要告訴Python我們用的是哪個(gè)空間。