雖然Python是解釋性語言,可是它是面向對象的,可以進行對象編程。下面就來了解一下如何在Python中進行對象編程。
類是對現實一類事物的封裝
如何定義一個類:
class className:
block
注意類名後面有個冒號,在block塊裏面就能夠定義屬性和方法了。當一個類定義完以後,就產生了一個類對象。類對象支持兩種操做:引用和實例化。引用操做是經過類對象去調用類中的屬性或者方法,而實例化是產生出一個類對象的實例,稱做實例對象。
好比定義一個People類:
class people:
name = 'jack' #定義了一個屬性
#定義了一個方法
def printName(self):
print self.name
people類定義完成以後就產生了一個全局的類對象,能夠經過類對象來訪問類中的屬性和方法了。當經過people.name(至於爲何能夠直接這樣訪問屬性後面再解釋,這裏只要理解類對象這個概念就好了)來訪問時,people.name中的people稱爲類對象,這點和C++中的有所不一樣。固然還能夠進行實例化操做,p=people( ),這樣就產生了一個people的實例對象,此時也能夠經過實例對象p來訪問屬性或者方法了(p.name).
理解了類、類對象和實例對象的區別以後,咱們來了解一下Python中屬性、方法和函數的區別。
在上面代碼中註釋的很清楚了,name是一個屬性,printName( )是一個方法,與某個對象進行綁定的函數稱做爲方法。通常在類裏面定義的函數與類對象或者實例對象綁定了,因此稱做爲方法;而在類外定義的函數通常沒有同對象進行綁定,就稱爲函數。
二.屬性
在類中咱們能夠定義一些屬性,好比:
class people:
name = 'jack'
age = 12html
p = people()
print p.name,p.age
定義了一個people類,裏面定義了name和age屬性,默認值分別爲'jack'和12。在定義了類以後,就能夠用來產生實例化對象了,這句p = people( )實例化了一個對象p,而後就能夠經過p來讀取屬性了。這裏的name和age都是公有的,能夠直接在類外經過對象名訪問,若是想定義成私有的,則需在前面加2個下劃線 ' __'。
class people:
__name = 'jack'
__age = 12python
p = people()
print p.__name,p.__age(會報錯,私有屬性只能在類的內部使用)
提示找不到該屬性,由於私有屬性是不可以在類外經過對象名來進行訪問的。在Python中沒有像C++中public和private這些關鍵字來區別公有屬性和私有屬性,它是以屬性命名方式來區分,若是在屬性名前面加了2個下劃線'__',則代表該屬性是私有屬性,不然爲公有屬性(方法也是同樣,方法名前面加了2個下劃線的話表示該方法是私有的,不然爲公有的)。
三.方法
在類中能夠根據須要定義一些方法,定義方法採用def關鍵字,在類中定義的方法至少會有一個參數,,通常以名爲'self'的變量做爲該參數(用其餘名稱也能夠),並且須要做爲第一個參數。下面看個例子:
class Peopel:
__name='jack'
__age=10
def getName(self)
return self.__name
def getAge(self):
return self.__age
若是對self很差理解的話,能夠把它當作C++中類裏面的this指針同樣理解,就是對象自身的意思,在用某個對象調用該方法時,就將該對象做爲第一個參數傳遞給self。
五.類屬性、實例屬性、類方法、實例方法以及靜態方法
在瞭解了類基本的東西以後,下面看一下python中這幾個概念的區別。
先來談一下類屬性和實例屬性
在前面的例子中咱們接觸到的就是類屬性,顧名思義,類屬性就是類對象所擁有的屬性,它被全部類對象的實例對象所共有,在內存中只存在一個副本,這個和C++中類的靜態成員變量有點相似。對於公有的類屬性,在類外能夠經過類對象和實例對象訪問。
class people:
name = 'jack' #公有的類屬性
__age = 12 #私有的類屬性
p = people()
print p.name #正確
print people.name #正確
print p.__age #錯誤,不能在類外經過實例對象訪問私有的類屬性
print people.__age #錯誤,不能在類外經過類對象訪問私有的類屬性
在類外對類對象people進行實例化以後,產生了一個實例對象p,而後p.age = 12這句給p添加了一個實例屬性age,賦值爲12。這個實例屬性是實例對象p所特有的,注意,類對象people並不擁有它(因此不能經過類對象來訪問這個age屬性)。固然還能夠在實例化對象的時候給age賦值。
class people:
name = 'jack'
#__init__()是內置的構造方法,在實例化對象時自動調用
def __init__(self,age):
self.age = age編程
p = people(12)
print p.name #正確
print p.age #正確函數
print people.name #正確
print people.age #錯誤this
下面來看一下類方法、實例方法和靜態方法的區別。
類方法:是類對象所擁有的方法,須要用修飾器"@classmethod"來標識其爲類方法,對於類方法,第一個參數必須是類對象,通常以"cls"做爲第一個參數(固然能夠用其餘名稱的變量做爲其第一個參數,可是大部分人都習慣以'cls'做爲第一個參數的名字,就最好用'cls'了),可以經過實例對象和類對象去訪問。
class people:
country = 'china'
#類方法,用classmethod來進行修飾
@classmethod
def getCountry(cls):
return cls.country指針
p = people()
print p.getCountry() #能夠用過實例對象引用
print people.getCountry() #能夠經過類對象引用
類方法還有一個用途就是能夠對類屬性進行修改:
class people:
country = 'china'
#類方法,用classmethod來進行修飾
@classmethod
def getCountry(cls):
return cls.country
@classmethod
def setCountry(cls,country):
cls.country = country
htm
p = people()
print p.getCountry() #能夠用過實例對象引用
print people.getCountry() #能夠經過類對象引用對象
p.setCountry('japan') blog
print p.getCountry()
print people.getCountry()
實例方法:在類中最常定義的成員方法,它至少有一個參數而且必須以實例對象做爲其第一個參數,通常以名爲'self'的變量做爲第一個參數(固然能夠以其餘名稱的變量做爲第一個參數)。在類外實例方法只能經過實例對象去調用,不能經過其餘方式去調用。
class people:
country = 'china'
#實例方法
def getCountry(self):
return self.country 繼承
p = people()
print p.getCountry() #正確,能夠用過實例對象引用
print people.getCountry() #錯誤,不能經過類對象引用實例方法
靜態方法:須要經過修飾器"@staticmethod"來進行修飾,靜態方法不須要多定義參數。
class people:
country = 'china'
@staticmethod
#靜態方法
def getCountry():
return people.country
print people.getCountry()
對於類屬性和實例屬性,若是在類方法中引用某個屬性,該屬性一定是類屬性,而若是在實例方法中引用某個屬性(不做更改),而且存在同名的類屬性,此時若實例對象有該名稱的實例屬性,則實例屬性會屏蔽類屬性,即引用的是實例屬性,若實例對象沒有該名稱的實例屬性,則引用的是類屬性;若是在實例方法更改某個屬性,而且存在同名的類屬性,此時若實例對象有該名稱的實例屬性,則修改的是實例屬性,若實例對象沒有該名稱的實例屬性,則會建立一個同名稱的實例屬性。想要修改類屬性,若是在類外,能夠經過類對象修改,若是在類裏面,只有在類方法中進行修改。
從類方法和實例方法以及靜態方法的定義形式就能夠看出來,類方法的第一個參數是類對象cls,那麼經過cls引用的一定是類對象的屬性和方法;而實例方法的第一個參數是實例對象self,那麼經過self引用的多是類屬性、也有多是實例屬性(這個須要具體分析),不過在存在相同名稱的類屬性和實例屬性的狀況下,實例屬性優先級更高。靜態方法中不須要額外定義參數,所以在靜態方法中引用類屬性的話,必須經過類對象來引用。
內置方法 說明
__init__(self,...) 初始化對象,在建立新對象時調用
__del__(self) 釋放對象,在對象被刪除以前調用
__new__(cls,*args,**kwd) 實例的生成操做
__str__(self) 在使用print語句時被調用
__getitem__(self,key) 獲取序列的索引key對應的值,等價於seq[key]
__len__(self) 在調用內聯函數len()時被調用
__cmp__(stc,dst) 比較兩個對象src和dst
__getattr__(s,name) 獲取屬性的值
__setattr__(s,name,value) 設置屬性的值
__delattr__(s,name) 刪除name屬性
__getattribute__() __getattribute__()功能與__getattr__()相似
__gt__(self,other) 判斷self對象是否大於other對象
__lt__(slef,other) 判斷self對象是否小於other對象
__ge__(slef,other) 判斷self對象是否大於或者等於other對象
__le__(slef,other) 判斷self對象是否小於或者等於other對象
__eq__(slef,other) 判斷self對象是否等於other對象
__call__(self,*args) 把實例對象做爲函數調用
http://www.cnblogs.com/simayixin/archive/2011/05/04/2036295.html
一.繼承和多繼承
在Python中類的繼承定義基本形式以下:
#父類
class superClassName:
block
#子類
class subClassName(superClassName):
block
在定義一個類的時候,能夠在類名後面緊跟一對括號,在括號中指定所繼承的父類,若是有多個父類,多個父類名之間用逗號隔開。以大學裏的學生和老師舉例,能夠定義一個父類UniversityMember,而後類Student和類Teacher分別繼承類UniversityMember:
class UniversityMember:
def __init__(self,name,age):
self.name = name
self.age = age
def getName(self):
return self.name
def getAge(self):
return self.age
class Student(UniversityMember):
def __init__(self,name,age,sno,mark):
UniversityMember.__init__(self,name,age) #注意要顯示調用父類構造方法,並傳遞參數self
self.sno = sno
self.mark = mark
def getSno(self):
return self.sno
def getMark(self):
return self.mark
class Teacher(UniversityMember):
def __init__(self,name,age,tno,salary):
UniversityMember.__init__(self,name,age)
self.tno = tno
self.salary = salary
def getTno(self):
return self.tno
def getSalary(self):
return self.salary
在大學中的每一個成員都有姓名和年齡,而學生有學號和分數這2個屬性,老師有教工號和工資這2個屬性,從上面的代碼中能夠看到:
1)在Python中,若是父類和子類都從新定義了構造方法__init( )__,在進行子類實例化的時候,子類的構造方法不會自動調用父類的構造方法,必須在子類中顯示調用。
2)若是須要在子類中調用父類的方法,須要以 父類名.方法 這種方式調用,以這種方式調用的時候,注意要傳遞self參數過去。
對於繼承關係,子類繼承了父類全部的公有屬性和方法,能夠在子類中經過父類名來調用,而對於私有的屬性和方法,子類是不進行繼承的,所以在子類中是沒法經過父類名來訪問的。
對於多重繼承,好比
class SubClass(SuperClass1,SuperClass2)
此時有一個問題就是若是SubClass沒有從新定義構造方法,它會自動調用哪一個父類的構造方法?這裏記住一點:以第一個父類爲中心。若是SubClass從新定義了構造方法,須要顯示去調用父類的構造方法,此時調用哪一個父類的構造方法由你本身決定;若SubClass沒有從新定義構造方法,則只會執行第一個父類的構造方法。而且若SuperClass1和SuperClass2中有同名的方法,經過子類的實例化對象去調用該方法時調用的是第一個父類中的方法。