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類建立的例項可以任意繫結屬性,如果需要對類本身繫結屬性,則需要在類中定義,這就區分了類屬性和例項屬性。
在編寫程式的時候,千萬不要把例項屬性和類屬性使用相同的名字,因為相同的名稱的例項屬性將遮蔽掉類屬性,但是當你刪除例項屬性後,再使用相同的名稱,訪問到的將是類屬性。