面向?qū)ο缶幊?/p>
基本思想:類和實例
類:用于定于抽象類型(比如人、汽車、花等抽象的一類事物)
實例:根據(jù)類的定義被創(chuàng)建出來的(比如人的實例有小明、小胡等具體的人,他們有年齡、性別和愛好等不同的屬性和方法)
15.1 python之定義類并創(chuàng)建實例
在Python中,類通過class?關(guān)鍵字定義。以Person為例,定義一個Person類如下:
class Person(object):
? ? pass
按照Python的編程習(xí)慣,類名以大寫字母開頭,緊接著是(object),表示該類是從哪個類繼承下來的。類的繼承將在后面的章節(jié)講解,現(xiàn)在我們只需要簡單地從object類繼承。
有了Person類的定義,就可以創(chuàng)建出具體的xiaoming、xiaohong等實例。創(chuàng)建實例使用類名+(),類似函數(shù)調(diào)用的形式創(chuàng)建:
xiaoming = Person()
xiaohong = Person()
15.2 python中創(chuàng)建實例屬性
雖然可以通過Person類創(chuàng)建出xiaoming、xiaohong等實例,但是這些實例看上除了地址不同外,沒有什么其他不同。在現(xiàn)實世界中,區(qū)分xiaoming、xiaohong要依靠他們各自的名字、性別、生日等屬性。
如何讓每個實例擁有各自不同的屬性?由于Python是動態(tài)語言,對每一個實例,都可以直接給他們的屬性賦值,例如,給xiaoming這個實例加上name、gender和birth屬性:
xiaoming = Person()
xiaoming.name = 'Xiao Ming'
xiaoming.gender = 'Male'
xiaoming.birth = '1990-1-1'
給xiaohong加上的屬性不一定要和xiaoming相同:
xiaohong = Person()
xiaohong.name = 'Xiao Hong'
xiaohong.school = 'No. 1 High School'
xiaohong.grade = 2
實例的屬性可以像普通變量一樣進(jìn)行操作:
xiaohong.grade = xiaohong.grade + 1
15.3 python中初始化實例屬性
雖然我們可以自由地給一個實例綁定各種屬性,但是,現(xiàn)實世界中,一種類型的實例應(yīng)該擁有相同名字的屬性。例如,Person類應(yīng)該在創(chuàng)建的時候就擁有name、gender?和birth?屬性,怎么辦?
在定義 Person 類時,可以為Person類添加一個特殊的__init__()方法,當(dāng)創(chuàng)建實例時,__init__()方法被自動調(diào)用,我們就能在此為每個實例都統(tǒng)一加上以下屬性:
class Person(object):
??? def __init__(self, name, gender, birth):
? ? ? ? self.name = name
? ? ? ? self.gender = gender
? ? ? ? self.birth = birth
__init__()?方法的第一個參數(shù)必須是self(也可以用別的名字,但建議使用習(xí)慣用法),后續(xù)參數(shù)則可以自由指定,和定義函數(shù)沒有任何區(qū)別。
相應(yīng)地,創(chuàng)建實例時,就必須要提供除self?以外的參數(shù):
xiaoming = Person('Xiao Ming', 'Male', '1991-1-1')
xiaohong = Person('Xiao Hong', 'Female', '1992-2-2')
有了__init__()方法,每個Person實例在創(chuàng)建時,都會有name、gender?和birth?這3個屬性,并且,被賦予不同的屬性值,訪問屬性使用.操作符:
print xiaoming.name# 輸出 'Xiao Ming'
print xiaohong.birth# 輸出 '1992-2-2'
要特別注意的是,初學(xué)者定義__init__()方法常常忘記了self?參數(shù):
>>> class Person(object):
...? ? def __init__(name, gender, birth):
...? ? ? ? pass
>>> xiaoming = Person('Xiao Ming', 'Male', '1990-1-1')
Traceback (most recent call last):
? File "", line 1, in
TypeError: __init__() takes exactly 3 arguments (4 given)
這會導(dǎo)致創(chuàng)建失敗或運行不正常,因為第一個參數(shù)name被Python解釋器傳入了實例的引用,從而導(dǎo)致整個方法的調(diào)用參數(shù)位置全部沒有對上。
15.4 python中訪問限制
我們可以給一個實例綁定很多屬性,如果有些屬性不希望被外部訪問到怎么辦?
Python對屬性權(quán)限的控制是通過屬性名來實現(xiàn)的,如果一個屬性由雙下劃線開頭(__),該屬性就無法被外部訪問??蠢樱?/p>
class Person(object):
? ? def__init__(self, name):
? ? ? ? self.name = name
? ? ? ? self._title = 'Mr'
? ? ? ? self.__job= 'Student'
p = Person('Bob')
print p.name
# => Bob
print p._title
# => Mr
print p.__job
# => Error
Traceback (most recent call last):
? File "", line 1, in AttributeError: 'Person' object has no attribute '__job'
可見,只有以雙下劃線開頭的"__job"不能直接被外部訪問。
但是,如果一個屬性以"__xxx__"的形式定義,那它又可以被外部訪問了,以"__xxx__"定義的屬性在Python的類中被稱為特殊屬性,有很多預(yù)定義的特殊屬性可以使用,通常我們不要把普通屬性用"__xxx__"定義。
以單下劃線開頭的屬性"_xxx"雖然也可以被外部訪問,但是,按照習(xí)慣,他們不應(yīng)該被外部訪問。