使用Python有一段時間了,感覺小蟒蛇是門在很多方面很給力的語言,不光是它強大的函數式編程,還有他它的可以不創建類和對象來實現面向對象模式的大部分功能——靠的是它強大的數據類型,列表和字典。
用字典的鍵來代表對象的屬性,直接賦值,方法所有人公用。對于我這樣的新手來說,這招可說是屢試不爽,簡單的小功能小游戲輕松搞定,有效減少了代碼編寫量與思考時間,甚至很多時候我忘了它是們面向對象的語言了。然而,有些情況下(雖然我還沒遇到),python中類和對象可能還是要的。本著技多不壓身的原則,今天我就現學現賣,給大家介紹一下Python中的類與對象的使用。同時,也替小蟒蛇證明一下,咱真的是面向對象的語言!
一、python中的類
簡單介紹下python中的類,首先是類的定義格式:
classstudent(object):
......
怎么樣,夠簡潔吧?去掉了一切多余的東西,Python中的類定義被縮到了最簡——只要一個class關鍵字,一個類名即可,當然,你也可以加個括號指定繼的父類。
創建對象的方法同樣也很簡潔:
s?=?student()
與java不同,這里連new關鍵字都去掉了,自我猜測與python內部架構不同有關,后面有機會再研究。
然后,是類的初始化函數,創建對象時自動調用:
def__init__(self)?:
#要執行的初始化操作
你可以同時為自己的類設定屬性并賦初值,實現構造方法的功能:
def__init__(self,?age?=20,?school?=?‘HNU’?):
self.age?=?age
selfschool?=?school
這里注意兩點:
1 init 函數名的兩側分別要有兩個下劃線 _? (注意是兩個哦)
2 init 方法須有參數且的第一個參數必須為self(其實也不是死規定,這個后面會講)
這樣的限定似乎和python自由的原則稍有違背,但為了更大的自由,這點犧牲也是迫不得已啊,因為這樣系統可以”認出”這個函數,至于self后面會講。
最后,你可以向java里那樣給你的類賦予其他的屬性和方法
defset_name(self,name):
self.name?=?name
defcodeing(self,?language?=?‘Python’):
printself.name?+?‘在寫’?+?language
二?、解秘self
看了前面幾個例子,你大概發現了:凡是python類中的所有方法都要有一個self參數,而且這個self似乎和java中的this關鍵字很像。
沒錯,這個self確實和this很像,但是這二者還是有蠻大區別的,為了更好地理解self,我們不妨多問幾個為什么:
1? self是什么?
想知道這個self本質是什么,最直接的方法就是打印了。為此,我們建立一個簡單的類people,實例化時會打印self:
classpeople:
def__init__(self):
printself
按F5運行,輸入測試代碼:
p?=?people()
得到打印的結果:
<__main__.people?instance?at0x0206D5F8>
不管__main__是啥,我們至少知道了,self是people在內存地址0x0206D5F8處的實例。因此,self在這里與java中的this一樣,代表的都是當前對象的地址,可以用來調用當前類中的屬性和方法,實例見上。
2 self與this有什么不同?
首先,與多數時候可以省略的this不同,self在任何情況下絕不能省略。對于這點,我是這樣理解的:與java中的class不同,python中的class本質上是一個變量,只不過它里面的函數和屬性我們可以自定義,所有的方法調用都要由類本身來執行,而對象名反而成為了參數,看起來就python在和我們玩一個文字游戲,舉個例子:
s?=?student()
這是條創建對象的語句,python在執行時做了一個變換:
student.__init__(s)
同樣的,
s.coding('python')
在執行時換成了:
student.coding(s,'python')
所以,我們很容易理解為什么類中的方法必須要帶self參數了。是python與java中class的不同決定了this和self本質的不同。
2 self一定非得是self嗎?
你也許感覺到了,self其實就是一個普通參數,所以,self在python中不能算是關鍵字,因為你可以給他任意起名——myself、yourself啥都沒問題,甚至abc這種腦殘名字都可以的,所以,你大可這樣做:
defmust_self(not_self):
Print?not_self
執行這個函數
p.must_self()
最后還是可以得到打印的結果:
<__main__.people?instance?at0x0206D5F8>
因此,self在python中不算是關鍵字,它只是當前對象的地址的一個象征,我們可以任意命名,只不過為了交流方便,python社區中約定俗成地把它叫做self,你也完全不必墨守成規。
3 self還有什么用?
好了,到此為止我們探討了self的本質,并且知道,self可以實現java中this的全部功能,但是,你或許想問,它難道就沒有更多的用途了嗎?
其實是有的,那就是區分全局變量函數和類中的變量函數。(有篇博客作者把這叫做“防止非限定調用引起的全局變量”,一開始搞得我一頭霧水,不知道他怎么想的)
Python中,類之外可以定義很多全局變量和函數,這是它與java明顯的不同。為了解釋器準確的找到函數或變量,需要使用self來限定方法變量的區域,這樣解釋器就能快速知道你調用的是類中的變量還是全局的變量了。例子如下:
a?=1
defsay():
print'調用了全局方法'
classpeople:
a?=100
defsay(self):
print'調用了類的方法'
defdo(self):
say()
print'a?=?',a
這里我們定義了兩對同名的變量和函數,a和say,看一看do方法會執行哪一個
p?=?people()
p.do()
運行結果:
調用了全局方法
a?=1
顯然,變量重名并不影響調用,而在不用self限定時,系統會默認調用全局變量和方法,只有用self才能調用類自己的方法和變量 :
a?=1
defsay():
print'調用了全局方法'
classpeople:
a?=100
defsay(self):
print'調用了類的方法'
defdo(self):
say()
self.say()
print'a?=?',?a
print'self.a?=?',self.a
p?=?people()
p.do()
運行結果:
調用了全局方法
調用了類的方法
a?=1
self.a?=100
好了,關于類的使用與self大概就介紹這些,但不知道你們有沒有這種感覺,那就是python中使用類有點怪怪的,當然,很大一部分原因和那無所不在的self有關。不過,我的觀點是,python的創始者也不支持你在程序中使用類。因為強大的字典和列表已經可以輕松實現類的很多功能,所以類存在的必要性并不是特別大。而且,想要把java的開發模式硬搬到python里也無疑是個愚蠢的決定,因為在我眼中,python是門比java高級的多,也靈活得多的語言,它有自己的Coding
style,不要盲從他人。