python筆記--面向對象
面向對象編程
面向對象編程是一種編程方式,需要使用 “類” 和 “對象” 來實現:
類就是一個模板,模板裏可以包含多個函數,函數裏實現一些功能,實現對具有共同特征的事物的描述;
對象是類的實體,是一種數據類型。它不存在內存中,不能被直接操作,只有被實例化對象時,才會變的可操作。舉例說明:
#!/usr/bin/env python # -*- coding:utf-8 -*- class Student(): #calss是關鍵字,表示類Student是類的名稱,通常首字母大寫。 s=100 #類屬性,屬於全局變量。 ‘’’ 這是一個測試類#給類添加註釋 ‘’’ def name(self,name): #類中的函數,第一個參數必須是self。 print ‘I am %s‘%name def score(self): print self.s #方法中調用類屬性 obj=Student() #obj就是對象的實例化,可使用tyte(obj)查看其類型。 obj.name(‘zhangsan‘) #調用類的方法,輸出結果為”I am zhangsan”
一、__init__初始化實例屬性
python中定義了一個__init__方法,可以初始化類變量、傳遞類的參數,例如:
#初始化類變量
#!/usr/bin/env python # -*- coding:utf-8 -*- class Student(): def __init__(self): #__init__函數定義到類的開頭 self.name=‘zhangsan‘ #初始化變量,在以後的函數中可以調用。 self.score=100 def print_score(self): print ‘%s:%s‘%(self.name,self.score) #調用self.name f=Student() f.print_score()
註意:self.name 變量是一個實例屬性,只能在類方法中使用。
#傳參
#!/usr/bin/env python # -*- coding:utf-8 -*- class Student(): def __init__(self,a,b): self.name=a #初始化變量,只不過賦予的不是固定值,是一個可變參數。 self.score=b def print_score(self): print ‘%s:%s‘%(self.name,self.score) f=Student(‘zhangsan‘,‘100‘) #定義參數,傳遞給__init__函數 f.print_score()
註意:我們沒有專門調用__init__方法,只是在創建一個類的新實例的時候,把參數包括在圓括號內跟在類名後面,從而傳遞給__init__方法。
二、私有屬性
以雙下劃線開頭的變量,表示私有變量,受保護的,只能類本身能訪問,連子類也不能訪問,例如:
#!/usr/bin/env python class Info(): def __init__(self): self.__name=‘zhangsan‘ def say(self): print self__name a=Info() print a.__name
執行以上代碼會報錯:AttributeError: Info instance has no attribute ‘__name‘
事實上這是一種偽私有,例如:
#!/usr/bin/env python class Info(): def __init__(self): self.__name=‘zhangsan‘ def say(self): print self__name a=Info() print a._Info__name #在屬性前面加上_classname依然可以打印出來
註意:Python 中的以雙下滑開頭的類方法名,在類實例化以後會自動被概念,在其名字前加 _classname ,因為名字被改了,所以自然無法用雙下滑開頭的名字被訪問,從而達到不可進入的目的。
詳細的私有屬性描述,可以參考:
http://blog.itpub.net/26250550/viewspace-1411768/
三、面向對象的三大特性
1.封裝
通過上面的例子,可以看到面向對象編程需要兩個步驟:
(1)將內容封裝到某處
通過創建類、實例化對象,其實就是將內容封裝到對象中了。
(2)從某處調用被封裝的內容
調用被封裝的內容,一般有兩種情況:
#通過對象直接調用(第一個例子)
#通過self間接調用(第二個例子)
2.繼承
子類繼承父類的屬性和方法,能夠提高代碼的重用。
#簡單繼承
#!/usr/bin/env python class Student(): def __init__(self,a,b): self.name=a self.score=b def print_score(self): print ‘%s:%s‘%(self.name,self.score) class One(Student):#子類:One,父類:Student pass f=One(‘zhangsan‘,100) print f.name#調用父類的屬性 f.print_score()#調用父類的方法 #輸出結果如下: zhangsan zhangsan:100
#子類實例初始化
如果子類實例屬性初始化了,那父類的屬性和方法是不會被繼承的:
#!/usr/bin/env python class Boy(): def __init__(self): self.sex=‘boy‘ self.height=‘170‘ def print_mes(self): print ‘sex:%s,hei:%s‘%(self.sex,self.height) class Name(Boy): def __init__(self): #子類初始化實例屬性 self.name=‘zhangsan‘ def print_name(self): print ‘name:%s‘%self.name f=Name() print f.name f.print_name() f.print_mes() #異常信息如下: AttributeError: Name instance has no attribute ‘sex‘
沒有找到父類中的屬性,說明父類中的方法並沒有被子類繼承。
解決方法一:
#!/usr/bin/env python class Boy(): def __init__(self): self.sex=‘boy‘ self.height=‘170‘ def print_mes(self): print ‘sex:%s,hei:%s‘%(self.sex,self.height) class Name(Boy): def __init__(self): Boy.__init__(self) #將父類的__init__方法添加到子類中 self.name=‘zhangsan‘ def print_name(self): print ‘name:%s‘%self.name f=Name() print f.name f.print_name() f.print_mes()
解決方法二:
#!/usr/bin/env python class Boy(object): #需要指定基類object(新式類) def __init__(self): self.sex=‘boy‘ self.height=‘170‘ def print_mes(self): print ‘sex:%s,hei:%s‘%(self.sex,self.height) class Name(Boy): def __init__(self): super(Name, self).__init__() #使用super函數(super只能用於新式類) self.name=‘zhangsan‘ def print_name(self): print ‘name:%s‘%self.name f=Name() print f.name f.print_name() f.print_mes()
#多重繼承
子類有多個父類,如果調用的屬性或方法在子類中沒有,就會從父類中查找。在經典類和新式類中,查找的方式不同。python3.0之後不再經典類,統一為新式類。
經典類:
默認沒有父類,多繼承情況下,會按照深度優先方式查找。
新式類:
有繼承的類,如果沒有,可以繼承 object。多繼承情況下,會按照廣度優先方式查找。
舉例說明:
class D: #經典類 def bar(self): print ‘D.bar‘ class C(D): def bar(self): print ‘C.bar‘ class B(D): def bar(self): print ‘B.bar‘ class A(B, C): def bar(self): print ‘A.bar‘ a = A() a.bar()
執行bar方法時:
首先去A類中查找,如果A類中沒有,則繼續去B類中找,如果B類中沒有,則繼續去D類中找,如果D類中麽有,則繼續去C類中找,如果還是未找到,則報錯。
所以,查找順序:A --> B --> D --> C
在上述查找bar方法的過程中,一旦找到,則尋找過程立即中斷,便不會再繼續找了。
class D(object): #新式類 def bar(self): print ‘D.bar‘ class C(D): def bar(self): print ‘C.bar‘ class B(D): def bar(self): print ‘B.bar‘ class A(B, C): def bar(self): print ‘A.bar‘ a = A() a.bar()
執行bar方法時:
首先去A類中查找,如果A類中沒有,則繼續去B類中找,如果B類中沒有,則繼續去C類中找,如果C類中麽有,則繼續去D類中找,如果還是未找到,則報錯。
所以,查找順序:A --> B --> C --> D
在上述查找bar方法的過程中,一旦找到,則尋找過程立即中斷,便不會再繼續找了。
#多態
class F1: pass class S1(F1): def show(self): print ‘S1.show‘ class S2(F1): def show(self): print ‘S2.show‘ def Func(obj): print obj.show() s1_obj = S1() Func(s1_obj) s2_obj = S2() Func(s2_obj) #為了讓Func函數既可以執行S1對象的show方法,又可以執行S2對象的show方法,所以,定義了一個S1和S2類的父類,而實際傳入的參數是:S1對象和S2對象。
從上面這個例子可以看出,相同的消息可能會送給多個不同的對象,而系統可依據對象所屬類,引發對應類的方法,而有不同的行為,這就是多態的特點。
本文出自 “網絡技術” 博客,請務必保留此出處http://fengjicheng.blog.51cto.com/11891287/1930542
python筆記--面向對象