python--面對對象編程

面對對象基礎

使用面向對象編程能夠大幅度提高程序的複用率,降低後期的維護成本,提高軟件的可靠性和可伸縮性。

面向過程與面向對象

面向過程:首先分析出解決問題所需要的步驟,然後用函數把這些步驟一步一步實現,使用的時候依次調用這些函數即可。以“五子棋”程序爲例,面向過程的設計思路就是首先分析問題的步驟:①開始遊戲;②黑子先走;③繪製畫面;④判斷輸贏;⑤輪到白子;⑥繪製畫面;⑦判斷輸贏;⑧返回步驟②;⑨輸出最後結果。

面向對象:編程思想把構成問題的事務分解成各個對象,這些對象沒有先後的順序,它們共同作用構成了整個系統。以“五子棋”程序爲例,整個系統可以劃分爲 3 類對象:①玩家對象,即黑白雙方;②棋盤對象,負責繪製畫面;③規則系統,負責判定諸如犯規、輸贏等。第一類對象負責接受用戶輸入,並告知第二類對象棋子佈局的變化,棋盤對象接收到了棋子的變化就要負責在屏幕上面顯示出這種變化,同時利用第三類對象來對棋局進行判定。

面向對象基礎概念

  1. 基本概念
    (1)對象:一切事務皆對象。
    (2)類:類是對象的模板。一個類所包含的方法和數據描述一組對象的共同屬性和行爲。
  2. 主要特徵
    (1) 封裝性:將數據和方法封裝在類中,用戶只能看到公有方法,並不知道實現方法的細節。類相當於一個黑箱。
    (2) 繼承性:一個類可以定義另一個類。繼承分爲單繼承(一個子類只有一父類)和多重繼承(一個類有多個父類)。
    (3) 多態性:同一消息爲不同的對象接受時可產生完全不同的行爲。

類的定義與使用

類的定義

class Animal:
    count=0
    legs=[]
    #類的初始化函數
    def __init__(self,name):
        self.name=name
        
    #創建類中的函數
    def eat(self):
        print("I can eat")
  • __init__是該類的初始化函數,當創建一個對象後,會自動調用__init__,用於初始化一個對象的數據;
  • 任何python類方法的第一個參數都是self,這個參數類似於java中的this。

類的使用

類是抽象的模板,對象是類的實例。python創建一個對象不需要使用new操作符,直接調用類函數。

dog1=Animal('dog')
dog1.eat()  
# I can eat

類的屬性和方法

類的屬性

class Animal:
    count=0
    legs=[]
    #類的初始化函數
    def __init__(self,name):
        self.name=name

    #創建類中的函數
    def eat(self):
        print("I can eat")
dog1=Animal('dog')
print(Animal.count) #0
print(Animal.legs) #[]
print(dog1.name) #dog

count、legs、name爲該類的數據屬性,這些數據屬性分爲類數據屬性(count、legs)和實例數據屬性(name)。

類的特殊屬性:

類屬性 含義
__name__ 類的名字
__doc__ 類的文檔字符串
__bases__ 類的所有父類組成的元素
__dict__ 類的屬性組成的字典
__module__ 類所屬的模塊
__class__ 類對象的類型

類的方法

在一個類中,可能出現三種方法:實例方法、類方法和靜態方法。
(1) 實例方法
實例方法的第一個參數必須是"self"。

class Animal:
    count=0
    legs=[]
    #類的初始化函數
    def __init__(self,name):
        self.name=name

    #創建類中的函數
    def eat(self):
        print("I can eat")
dog1=Animal('dog')
dog1.eat()  #I can eat

(2) 類方法
類方法以cls作爲第一個參數,cls表示類本身,定義時使用@classmethod裝飾器。通過cls可以訪問類的相關屬性。

class Animal:
    count=0
    legs=[]
    #類的初始化函數
    def __init__(self,name):
        self.name=name

    @classmethod
    def printClassInfo():
        print(cls.__name__)
        
Animal.printClassInfo() #Animal
cat=Animal('cat')
cat.printClassInfo() #Animal

(3) 靜態方法
靜態方法沒有參數限制,既不需要實例參數,也不需要類參數,定義的時候使用@staticmethod裝飾器。

class Animal:
    count=5
    legs=[]
    #類的初始化函數
    def __init__(self,name):
        self.name=name

    @staticmethod
    def printClassAttr():
        print(Animal.count)

Animal.printClassAttr() # 5
cat=Animal('cat')
cat.printClassAttr() # 5

實例方法只能通過實例進行調用;靜態方法和類方法,可以通過類名和實例兩種方式進行調用。

特殊的類方法:

類屬性 含義
__del__ 析構函數
__len__ 獲得長度
__call__ 函數調用
__dict__ 類的屬性組成的字典
__add__ 加運算
__sub__ 減運算

訪問控制

Python中沒有像Java中private、protected等訪問控制的關鍵字,但在Python編碼中,使用一些約定來進行訪問控制。
(1) 名稱前的雙下劃線
如果一個函數、類方法或屬性的名字以兩個下劃線開始(但不是結束),它是私有的。
(2) 名稱前的單下劃線
在Python中,一般約定以單下劃線“_”開頭的變量、函數爲模塊私有的。也就是說“from 模塊名 import *”將不會引入以單下劃線“_”開頭的變量、函數。
(3) 名稱前後的雙下劃線
這種用法表示Python中特殊的方法名。例如,當定義一個類時,經常會重寫“__init__”方法。

構造函數和析構函數

(1) __init__ ()構造方法
構造函數是一種特殊的方法,主要用來在創建對象時初始化對象。若實現了__init__()方法,就調用這個方法。

class test():
    def __init__(self):
        print("__init__")
    def __del__(self):
        print("__del__")
    def common(self):
        print("common")
t1=test()

調用結果:

__init__
__del__

說明在創建t1時,__init__()方法被執行了。

(2) __del__()析構方法
當使用del刪除對象時,會調用它本身的析構函數,另外當對象在某個作用域中調用完畢,也會調用析構函數,用來釋放內存空間

類的繼承

當一個類被其他的類繼承時,被繼承的類稱爲基類,又稱爲父類。繼承其他類屬性的類稱爲派生類,又稱爲子類。

類的簡單繼承

class Animal:
    def eat(self):
        print(self.name+' eat')
    def drink(self):
        print(self.name+' drink')
class Cat(Animal):
    def __init__(self,name):
        self.name=name
    def miaomiao(self):
        print('miaomiao')
class Dog(Animal):
    def __init__(self,name):
        self.name=name
    def wangwang(self):
        print('wangwang')
c1=Cat('jerry')
c1.eat()
d1=Dog('mike')
d1.drink()

運行結果:

jerry eat
mike drink

當在Python中出現繼承的情況時,一定要注意初始化函數__init__的行爲。
(1) 如果子類沒有定義自己的初始化函數,父類的初始化函數會被默認調用;如果要實例化子類的對象,則只能傳入父類的初始化函數對應的參數,否則會出錯。
(2) 如果子類定義了自己的初始化函數,而沒有顯式調用父類的初始化函數,則父類的屬性不會被初始化。
(3) 如果子類定義了自己的初始化函數,顯式調用父類,則子類和父類的屬性都會被初始化。

類的多重繼承

使用多重繼承需要注意圓括號中父類名字的順序。如果父類中有相同的方法名,而在類中使用時未指定父類名,則Python解釋器將從左至右搜索。

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):
    pass
a=A()
a.bar() #B.bar
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(C,B):
    pass
a=A()
a.bar()  # C.bar

類的重載

當繼承某一個或幾個類時,當前定義的類也繼承父類的方法。重載,是指重新定義父類中的方法。

方法重載

方法重載指的是重載父類的方法。

#重載了構造函數和show父類的方法
class People:
    def __init__(self,name):
        self.name=name
    def show(self):
        print('father')
    def setName(self,name):
        print(name)


class P1(People):
    def __init__(self,name,age):
        self.name=name
        self.age=age
    def show(self):
        print('son')
p1=P1('mike',23)
p1.show()
p1.setName('marry')

運算符重載

在類中,運算符對應類中的一些專有方法。因此運算符的重載實際上是對運算符對應的專有方法的重載。
例如+操作符對應__add__方法:

class List:
    __mylist=[]
    def __init__(self,*args):
        self.__mylist=[]
        for arg in args:
            self.__mylist.append(arg)
    def __add__(self, n):
        for i in range(0,len(self.__mylist)):
            self.__mylist[i]=self.__mylist[i]+n
        return self.__mylist
    def show(self):
        print(self.__mylist)
list=List(1,2,3,4,5)
list.show()  # [1, 2, 3, 4, 5]
list1=list + 5
print(list1)  #[6, 7, 8, 9, 10]

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章