1. 程式人生 > >Python 之 基礎面向物件程式設計

Python 之 基礎面向物件程式設計

注意:本文轉自微信公眾號 “Python互動中心”,覺得作者寫的很好,我這邊自己收藏學習。

1、面向物件程式設計

面向物件程式設計Object Oriented Programming簡稱OOP,是一種程式設計思想。OOP把物件作為程式的基本單元,一個物件包含了資料和操作資料的函式

面向過程的程式設計把計算機程式視為一系列的命令集合,即一組函式的順序執行。為了簡化程式設計,面向過程把函式連續切分為子函式,即把大塊函式切割成小塊函式來降低系統的複雜度。

而面向物件的程式設計把計算機程式視為一組物件的集合,而每個物件都可以接收其他物件發過來的訊息,並處理這些訊息,計算機程式的執行就是一系列訊息在各個物件之間的傳遞。

在Python中所有資料型別都可以視為物件,當然也可以自定義物件。自定義的物件資料型別就是面向物件中的類(Class)的概念。面向物件的抽象程度又比函式要高,因為一個Class既包含資料,又包含操作資料的方法。

class Solution(object):
    def __init__(self,name,score):
        self.name  = name
        self.score = score

    def print_info(self):
        print("This Student Name is %s , and He's Score is %d"%(self.name,self.score))

if __name__ == "__main__":
    Student = Solution('Python',99)
    Student.print_info()
    print(Student.name)
    print(Student.score)


2、類和例項

 class 後面緊接著的是類名,即Solution,類名通常是大寫開頭的單詞,緊接著是(object),表示該類是從哪個類繼承下來的,通常如果沒有合適的繼承類,就使用object類,這是所有類最終都會繼承的類。

定義好了Solution類,就可以根據Student類創建出Student的例項,建立例項是通過類名+()實現的。

3、資料封裝

類本身擁有資料和方法,相當於將“資料”封裝起來。對於外部來說,並不需要知道內部邏輯

4、訪問限制

Class可以有屬性的方法,我們可以對屬性和方法進行控制,以達到允許或者不允許外部訪問的目的。如果要讓內部屬性不被外部訪問,可以把屬性的名稱前加上兩個下劃線,在Python中,例項的變數名如果以雙下劃線開頭,就變成一個私有變數(Private),只有內部可以訪問,外部不能訪問。

class Solution(object):
    def __init__(self,name,score):
        self.__name  = name
        self.__score = score

    def print_info(self):
        print("This Student Name is %s , and He's Score is %d"%(self.__name,self.__score))

    def get_name(self):
        return self.__name

    def get_score(self):
        return self.__score

    def set_score(self,score):
        if 0<= score <= 100:
            self.__score = score
        else:
            raise ValueError('bad Score')

if __name__ == "__main__":
    Student = Solution('Python',199)
    Student.print_info()
    print(Student.get_name())
    print(Student.get_score())
    Student.set_score(199)


在Python中,變數名類似__xxx__的,也就是以雙下劃線開頭,並且以雙下劃線結尾的,是特殊變數,特殊變數是可以直接訪問的,不是Private變數,所以不能用__name_、__score__這樣的變數名。

5、繼承和多型

在OOP程式設計中,當我們定義一個class的時候,可以從某個現有的class繼承,新的class稱為子類(subclass),而被繼承的class稱為基類、父類或超類(Base Class、Super Class)。

class Animal(object):
    def Base(self):
        print('Please Call Me Animal...')

    def Run(self):
        print('Aniaml is Running...')

class Dog(Animal):
    def Run(self):
        print('Dog is Running...')

class Cat(Animal):
    def Run(self):
        print('Cat is Running...')


animal = Animal()
animal.Base()
animal.Run()

dog = Dog()
dog.Base()
dog.Run()

cat = Cat()
cat.Base()
cat.Run()


當子類和父類都存在相同的Run()方法時,我們說,子類Run()覆蓋了父類Run(),在程式碼執行的時候,總是會呼叫子類的Run(),這樣,我們就獲得繼承的另一個好處:多型。在繼承關係中,如果一個例項的資料型別是某個子類,那它的資料型別也可以被看做是父類。但是,反過來就不行了。

對於一個變數,我們只需要知道它是Animal型別,無需確切地知道它的子型別,就可以放心的呼叫Run方法,而具體的Run()方法是作用在Animal、Dog、Cat還是Tortoise物件上,由執行時該物件的確切型別決定,這就是多型的精髓:呼叫方只管呼叫,不管細節,而當我們新增一種Animal子類時,只要確保Run()方法編寫正確,不管原來的程式碼如何呼叫。這就是著名的開閉原則。

對擴充套件開放:允許新增Animal子類;

對修改封閉:不需要修改依賴Animal型別的外部函式。

6、鴨子型別

對於靜態語言(例如Java)來說,如果需要傳入Animal型別,則傳入的物件必須是Animal型別或者其它的子類,否則,將無法呼叫Run()方法。

對於像Python這樣的動態語言來說,則不一定需要傳入Animal型別。我們只需要保證傳入的物件有一個Run()方法就可以了。這就是動態語言的“鴨子型別”,它並不要求嚴格的繼承體系,一個物件只要“看起來像鴨子,走起路來像鴨子”,那麼它就可以看做時鴨子。

7、例項屬性和類屬性

Python類建立的例項可以任意繫結屬性,如果需要對類本身繫結屬性,則需要在類中定義,這就區分了類屬性和例項屬性。

在編寫程式的時候,千萬不要把例項屬性和類屬性使用相同的名字,因為相同的名稱的例項屬性將遮蔽掉類屬性,但是當你刪除例項屬性後,再使用相同的名稱,訪問到的將是類屬性。