python—面向對象編程


面向對象編程簡單來說就是基於對  和 對象 的使用,所有的代碼都是通過類和對象來實現的編程就是面向對象編程!

面向對象的三大特性:封裝、繼承、多態

首先創建一個類

#使用class創建一個School類,類中有個student方法
class School:
    def student(self):
        pass
a1=School()

一、封裝

1、封裝:將某些內容先封裝到一個地方,等到需要的時候再去調用

class School:
    def __init__(self,name,age):    #構造方法,創建對象是執行
        self.name=name
        self.age=age

#創建對象a1,a2
a1=School("zhangsan",18)
a2=School("lisi",18)

上面代碼實現的就是封裝的功能,把各自的name和age分別封裝到了self的name和age屬性中,就等於被封裝到了對象a1和a2中

類中定義的函數叫做方法,帶有__init__的函數稱為構造方法,在創建a1,a2對象時會自動執行。

2、調用:調用有兩種方式,通過對象直接調用和通過self間接調用

通過對象直接調用

class School:
    def __init__(self,name,age):
        self.name=name
        self.age=age

    def student(self):
        print("name:%s,age:%s"%(self.name,self.age))
#創建對象a1,a2
a1=School("zhangsan",18)
a2=School("lisi",18)
print a1.name,a1.age
print a2.name,a2.age
#執行結果: zhangsan 18
      lisi 18

通過self間接調用

class School:
    def __init__(self,name,age):
        self.name=name
        self.age=age

    def student(self):
        print("name:%s,age:%s"%(self.name,self.age))
#創建對象a1,a2
a1=School("zhangsan",18)
a2=School("lisi",18)

#執行類中的方法時,通過self間接調用被封裝的內容
a1.student()
a2.student()
#執行結果:
#name:zhangsan,age:18
#name:lisi,age:18

二、繼承

1、繼承:既派生類(子類)可以繼承基類(父類)的方法,我們可以將多個類共有的方法提取到父類當中,這樣子類僅需繼承父類而不必一一實現每個方法

在類名后面括號中寫上另一個類,表示繼承了那個類

#使用class創建一個School類
class School:
    def __init__(self,name,age):
        self.name=name
        self.age=age

    def student(self):
        print("name:%s,age:%s"%(self.name,self.age))
    def classroom(self):
        print("%s去教室"%self.name)

class SchoolA(School):  #SchoolA繼承School
    def __init__(self,name):
        self.name=name

class SchoolB(SchoolA): #SchoolB繼承SchoolA
    def __init__(self,name):
        self.name=name
#創建對象a1
a1=SchoolA("zhangsan")
a1.classroom()
#創建對象a2
a2=SchoolB("lisi")
a2.classroom()

#執行結果:
#   zhangsan去教室
#   lisi去教室

在上面代碼中我們可以看到,在SchoolA和SchoolB中都沒有classroom方法,但由於SchoolB繼承了SchoolA,而SchoolA又繼承了School,所以他們創建對象后都能

調用School中的classroom方法。

2、多繼承

在python中,類還可以繼承多個類,在繼承多個類時,他對類中的函數查找有兩種方式

  深度優先:類是經典類時,多繼承情況下,會按照深度優先方式查找

  廣度優先:類是新式類時,多繼承情況下,會按照廣度優先方式查找

(在python3.x中)都默認為廣度優先,但還是可以了解一下兩個的區別,新式類:當前類或者基類繼承了objiect類就叫新式類,否者就是經典類

在python2.7中

#python2.7中經典類
class A():
    def name(self):
        print("AAAAAA")
class B(A):
    pass
class C(A):
    def name(self):
        print("CCCCCC")
class D(B,C):
    pass
a1=D()
a1.name()   #輸出:AAAAAA
#查找順序:# 首先去自己D類中查找,如果沒有,則繼續去B類中找,沒有則繼續去A類中找,沒有則繼續去C類中找,如果還是未找到,則報錯
#深度優先:D-B-A-C
#python2.7中新式類
class A(object):
    def name(self):
        print("AAAAAA")
class B(A):
    pass
class C(A):
    def name(self):
        print("CCCCCC")
class D(B,C):
    pass
a1=D()
a1.name()   #輸出:CCCCCC
#查找順序:# 首先去自己D類中查找,如果沒有,則繼續去B類中找,沒有則繼續去C類中找,沒有則繼續去A類中找,如果還是未找到,則報錯
#廣度優先:D-B-C-A

上面兩個例子中我們可以看到,經典類和新式類輸出的結果是不一樣的,是因為他們的查找順序不一樣

python2.7中 廣度優先的前提條件:D繼承BC,BC又同時繼承A,只有滿足這個條件,新式類才會遵循廣度優先,否者不會,例:

class A(object):
    def name(self):
        print("AAAAAA")
class B(A):
    pass
class C:
    def name(self):
        print("CCCCCC")
class D(B,C):
    pass
a1=D()
a1.name()   #輸出:AAAAAA

如果C不在繼承A,那么就算你是新式類,他也會按照深度優先的順序查找

在python3.X之后就沒有了上面的這些區別,它的查找順序都是 廣度優先 

三、多態

python不支持多態,也用不到多態,python是一種多態語言,崇尚鴨子類型

 四、類中的成員

類中的成員:字段、方法、屬性

1、字段

字段:普通字段、靜態字段

class School:
    headmaster="王五"
    def __init__(self,name,age):
        self.name=name
        self.age=age

    def student(self):
        print("name:%s,age:%s"%(self.name,self.age))

#創建對象a1
a1=School("zhangsan",18)
print(a1.name)  #訪問普通字段
print(School.headmaster)    #訪問靜態字段

#執行結果:
#   zhangsan
#   王五

在上面代碼中,__init__函數中的就是普通字段,headmaster就是靜態字段

  普通字段:屬於對象,由對象來訪問,在內存中每個對象都要保存一份

  靜態字段:屬於類,由類直接訪問,在內存中只保存一份

2、方法

方法:普通方法、靜態方法、類方法

class School:
    headmaster="王五"
    def __init__(self,name,age):
        self.name=name
        self.age=age

    def student(self):  #普通方法 至少一個self
        print("普通方法")

    @staticmethod       #靜態方法 任意參數
    def classroom():
        print("靜態方法")

    @classmethod
    def dormitory(cls):    #類方法 只能一個cls
        print("類方法",cls)

#創建對象a1
a1=School("zhangsan",18)
a1.student()

School.classroom()    #訪問靜態方法
School.dormitory()     #訪問類方法

'''執行結果:
    普通方法
    靜態方法
    類方法 <class '__main__.School'>
    '''

普通方法:先創建一個對象,在用對象去調用這個方法

靜態方法:直接用類調用,可以有任意參數(靜態方法可以讓類直接調用,省去了普通方法創建對象的步驟)

類方法:直接用類調用,只能一個cls參數

    上面我們可以看到執行類方法時,輸出了他傳入的參數等於<class '__main__.School'>,是一個類,意思就是執行時,它會把當前的類當成參數傳進去。

3、屬性

屬性定義:裝飾器定義、靜態字段定義

(1)裝飾器定義

class School:
    headmaster="王五"
    def __init__(self,name,age):
        self.name=name
        self.age=age

    def student(self):  #方法
        print("方法")

    @property
    def classroom(self):    #屬性,加上@property裝飾器,僅有一個self參數
        print("屬性")

#創建對象a1
a1=School("zhangsan",18)
a1.student()    #調用方法
a1.classroom    #調用屬性

#執行結果:
#   方法
#   屬性

在上面代碼中可以看到,在方法上加上@property裝飾器就叫屬性,屬性和方法的區別就是調用時不用加括號

在新式類中,除了@property,還有另外兩種裝飾器

class School(object):
    def __init__(self,name,age):
        self.name=name
        self.age=age

    @property
    def classroom(self):    #屬性,加上@property裝飾器,僅有一個self參數
        print(self.name,self.age)
    @classroom.setter
    def classroom(self,age):
        self.age=age    #把age修改為傳入的參數
        print("修改",self.name,self.age)
    @classroom.deleter
    def classroom(self):
        del self.age        #刪除age
        print("刪除",self.name,self.age)

#創建對象a1
a1=School("張三",18)
a1.classroom    #1.執行后會自動調用@property方法
a1.classroom=20     #2.執行后會自動調用@classroom.setter的方法,並將20傳給age參數
del a1.classroom    #3.執行后會自動調用@classroom.deleter的方法

'''執行結果:
    張三 18
    修改 張三 20
    在執行3時會報錯,因為age已經在@classroom.deleter下面的方法里刪除了,所以輸出self.age時會出錯
'''

(2)靜態字段定義

class School(object):
    def __init__(self,name,age):
        self.name=name
        self.age=age

    def classroom(self):
        print(self.name,self.age)

    def classroom_update(self,age):
        self.age=age    #把age修改為傳入的參數
        print("修改",self.name,self.age)

    def classroom_del(self):
        del self.age        #刪除age
        print("刪除",self.name,self.age)

    obj=property(classroom,classroom_update,classroom_del)  #靜態字段方式定義屬性

#創建對象a1
a1=School("張三",18)
a1.obj  #1.執行后會自動調用classroom方法
a1.obj=20     #2.執行后會自動調用classroom_update的方法,並將20傳給age參數
del a1.obj    #3.執行后會自動調用classroom_delr的方法

4、公有成員和私有成員

在類中的每一個成員都有兩種形式:公有、私有

公有:都可以訪問      私有:只有在類的內部可以訪問

舉幾個例子

字段

class School(object):
    deg="" #公有靜態字段
    __cat=""   #私有靜態字段
    def __init__(self,name,age):
        self.name=name  #公有普通字段
        self.__age=age  #私有普通字段

    def dormitory(self):
        print(self.__age)

    def cat(self):
        print(School.__cat)

#創建對象a1
a1=School("張三",18)
#訪問普通字段
print(a1.name)  #輸出:張三
print(a1.age)   #報錯,提示沒有age,因為age是私有字段,只能間接內部訪問
a1.dormitory()  #只能通過類內部訪問私有字段
#訪問靜態字段
print(School.deg)   #輸出:狗
print(School.__cat) #報錯
a1.cat()        #輸出:貓   可以間接通過內部的cat方法反問私有靜態字段

方法

class School(object):

    def __init__(self,name,age):
        self.name=name
        self.__age=age

    def cat(self):  #公有方法
        print("cat")

    def __dog(self):   #私有方法
        print("dog")

    def doo(self):  #內部訪問私有方法
        a1.__dog()
#創建對象a1
a1=School("張三",18)
a1.cat()    #輸出:cat
a1.dog()    #報錯
a1.doo()    #輸出:dog  間接通過doo方法反問私有方法__dog

類中的其他成員也和上面的類似

如果想要強制訪問私有字段,可以通過(對象._類名__私有字段名)訪問,不建議強制訪問私有成員。

5、類中的特殊成員

(1)__doc__

class School(object):
    """類的描述信息"""
    def __init__(self,name,age):
        self.name=name
        self.__age=age

print(School.__doc__)   #輸出:類的描述信息

(2)__init__

在上面已經說過,在創建對象是自動執行

(3)__del__

當對象在內存中被釋放時,自動觸發執行

(4)__call__

在創建的對象后面加括號執行時,會自動執行類里的__call__方法

class School(object):

    def __call__(self, *args, **kwargs):
        print("觸發__call__方法")

a1=School()
a1()    #輸出:觸發__call__方法
School()()  #輸出:觸發__call__方法

(5)__dict__

獲取類或對象的所有成員

class School(object):
    """類的描述信息"""
    cat=""
    def __init__(self,name,age):
        self.name=name
        self.__age=age
    def dog(self):
        print("dog")

print(School.__dict__)  #獲取類中的成員
a1=School("張三",18)
print(a1.__dict__)  #獲取對象中的成員
'''
輸出:
{'cat': '貓', '__init__': <function School.__init__ at 0x000000000226C950>, '__dict__': <attribute '__dict__' of 'School' objects>, '__weakref__': <attribute '__weakref__' of 'School' objects>, '__module__': '__main__', 'dog': <function School.dog at 0x000000000226CAE8>, '__doc__': '類的描述信息'}
{'name': '張三', '_School__age': 18}
'''

(6)__str__

沒有__str__

class School(object):
    def __init__(self,name,age):
        self.name=name
        self.__age=age
a1=School("張三",18)
print(a1)   #輸出:<__main__.School object at 0x000000000222B278>

有__str__

class School(object):
    def __init__(self,name,age):
        self.name=name
        self.__age=age

    def __str__(self):
        return("print對象時的返回值")
a1=School("張三",18)
print(a1)   #輸出:print對象時的返回值

其他的特殊成員就不一一列舉了,因為大多數情況下也不會用到

詳細請看:http://www.cnblogs.com/wupeiqi/p/4766801.html


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM