python中的類與self

使用Python有一段時間了,感覺小蟒蛇是門在很多方面很給力的語言,不光是它強大的函數式編程,還有他它的可以不創建類和對象來實現面向對象模式的大部分功能——靠的是它強大的數據類型,列表和字典。

用字典的鍵來代表對象的屬性,直接賦值,方法所有人公用。對于我這樣的新手來說,這招可說是屢試不爽,簡單的小功能小游戲輕松搞定,有效減少了代碼編寫量與思考時間,甚至很多時候我忘了它是們面向對象的語言了。然而,有些情況下(雖然我還沒遇到),python中類和對象可能還是要的。本著技多不壓身的原則,今天我就現學現賣,給大家介紹一下Python中的類與對象的使用。同時,也替小蟒蛇證明一下,咱真的是面向對象的語言!

一、python中的類

簡單介紹下python中的類,首先是類的定義格式:

Python代碼

classstudent(object):

......

怎么樣,夠簡潔吧?去掉了一切多余的東西,Python中的類定義被縮到了最簡——只要一個class關鍵字,一個類名即可,當然,你也可以加個括號指定繼的父類。

創建對象的方法同樣也很簡潔:

Python代碼

s?=?student()

與java不同,這里連new關鍵字都去掉了,自我猜測與python內部架構不同有關,后面有機會再研究。

然后,是類的初始化函數,創建對象時自動調用:

Python代碼

def__init__(self)?:

#要執行的初始化操作

你可以同時為自己的類設定屬性并賦初值,實現構造方法的功能:

Python代碼

def__init__(self,?age?=20,?school?=?‘HNU’?):

self.age?=?age

selfschool?=?school

這里注意兩點:

1 init 函數名的兩側分別要有兩個下劃線 _? (注意是兩個哦)

2 init 方法須有參數且的第一個參數必須為self(其實也不是死規定,這個后面會講)

這樣的限定似乎和python自由的原則稍有違背,但為了更大的自由,這點犧牲也是迫不得已啊,因為這樣系統可以”認出”這個函數,至于self后面會講。

最后,你可以向java里那樣給你的類賦予其他的屬性和方法

Python代碼

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:

Python代碼

classpeople:

def__init__(self):

printself

按F5運行,輸入測試代碼:

Python代碼

p?=?people()

得到打印的結果:

Python代碼


<__main__.people?instance?at0x0206D5F8>

不管__main__是啥,我們至少知道了,self是people在內存地址0x0206D5F8處的實例。因此,self在這里與java中的this一樣,代表的都是當前對象的地址,可以用來調用當前類中的屬性和方法,實例見上。

2 self與this有什么不同?

首先,與多數時候可以省略的this不同,self在任何情況下絕不能省略。對于這點,我是這樣理解的:與java中的class不同,python中的class本質上是一個變量,只不過它里面的函數和屬性我們可以自定義,所有的方法調用都要由類本身來執行,而對象名反而成為了參數,看起來就python在和我們玩一個文字游戲,舉個例子:

Python代碼

s?=?student()

這是條創建對象的語句,python在執行時做了一個變換:

Python代碼


student.__init__(s)

同樣的,

Python代碼


s.coding('python')

在執行時換成了:

Python代碼


student.coding(s,'python')

所以,我們很容易理解為什么類中的方法必須要帶self參數了。是python與java中class的不同決定了this和self本質的不同。

2 self一定非得是self嗎?

你也許感覺到了,self其實就是一個普通參數,所以,self在python中不能算是關鍵字,因為你可以給他任意起名——myself、yourself啥都沒問題,甚至abc這種腦殘名字都可以的,所以,你大可這樣做:

Python代碼


defmust_self(not_self):

Print?not_self

執行這個函數

Python代碼


p.must_self()

最后還是可以得到打印的結果:

<__main__.people?instance?at0x0206D5F8>

因此,self在python中不算是關鍵字,它只是當前對象的地址的一個象征,我們可以任意命名,只不過為了交流方便,python社區中約定俗成地把它叫做self,你也完全不必墨守成規。

3 self還有什么用?

好了,到此為止我們探討了self的本質,并且知道,self可以實現java中this的全部功能,但是,你或許想問,它難道就沒有更多的用途了嗎?

其實是有的,那就是區分全局變量函數和類中的變量函數。(有篇博客作者把這叫做“防止非限定調用引起的全局變量”,一開始搞得我一頭霧水,不知道他怎么想的)

Python中,類之外可以定義很多全局變量和函數,這是它與java明顯的不同。為了解釋器準確的找到函數或變量,需要使用self來限定方法變量的區域,這樣解釋器就能快速知道你調用的是類中的變量還是全局的變量了。例子如下:

Python代碼


a?=1

defsay():

print'調用了全局方法'

classpeople:

a?=100

defsay(self):

print'調用了類的方法'

defdo(self):

say()

print'a?=?',a

這里我們定義了兩對同名的變量和函數,a和say,看一看do方法會執行哪一個

Python代碼


p?=?people()

p.do()

運行結果:

Python代碼


調用了全局方法

a?=1

顯然,變量重名并不影響調用,而在不用self限定時,系統會默認調用全局變量和方法,只有用self才能調用類自己的方法和變量 :

Python代碼


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,不要盲從他人。

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容

  • Android 自定義View的各種姿勢1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 172,813評論 25 708
  • 1. Java基礎部分 基礎部分的順序:基本語法,類相關的語法,內部類的語法,繼承相關的語法,異常的語法,線程的語...
    子非魚_t_閱讀 31,739評論 18 399
  • 小沈的本名叫什么我不知道,只知道他姓沈,安微六安人。小沈說他今年三十有六,十六歲來上海打工,也算老上海了,不過還是...
    湖邊人老劉閱讀 626評論 0 1
  • 把知識變成技術,這也是弓醫生說過的話。學到技術,改變思維。
    freshriver閱讀 59評論 0 0
  • 今天繼續給大家講小青蛙弗洛格的故事~睡衣晚會。 弗洛格、小鴨和野兔在小豬家過夜—他們在開"睡衣晚會"?,F在他們在玩...
    高田GT閱讀 1,423評論 1 1