1. 程式人生 > >python筆記--面向對象

python筆記--面向對象

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筆記--面向對象