Python OOP物件導向設計的類型方法(Instance, Class, Static ...
文章推薦指數: 80 %
基於讓程式碼便於閱讀與大量生產與維護之故,大家會採用物件導向(Object-oriented…. “Python OOP物件導向設計的類型方法(Instance, Class, ...
GetunlimitedaccessOpeninappHomeNotificationsListsStoriesWritePublishedinPythonEverywhere-fromBeginnertoAdvancedPythonOOP物件導向設計的類型方法(Instance,Class,StaticMethod)ThePeninsulaManila,Philippines,photobySeanYeh基於讓程式碼便於閱讀與大量生產與維護之故,大家會採用物件導向(Object-oriented)的方式來建構程式。
在物件導向的程式設計上,我們知道類別(class)是物件實體的設計藍圖。
我們會把物件的屬性(attribute)與方法(method)都寫入這個藍圖裡面。
在一個類別裡面放入很多的方法,每個方法都是一個函式,且函式裡面,又可以包含多個處理程序。
此外,除了方法外,類別裡面還容納了很多的屬性。
有哪些類型方法在進行Python物件導向設計時,會使用到下面幾總方法:實體方法(InstanceMethod)靜態方法(StaticMethod)類別方法(ClassMethod)抽象方法(AbstractMethod)其中以前三種方法(Instance,Class,StaticMethod)非常重要,(第四種抽象方法留待未來另行撰文說明)以下分別說明之:InstanceMethod實體方法當我們在學習建立物件時,建立的第一個class物件,採用的應該就是實體方法(InstanceMethod)。
實體方法,是我們大部分時候會使用到的方法,它必須要有self參數作為第一個參數。
當然,我們可以在self後面傳遞其他的參數,只不過self必須是第一個參數。
self參數會指向物件本身,透過它可以自由的存取物件的屬性(attribute)及其他方法(method),藉此來改變物件本身的狀態。
#類別classPerson:#實體方法defwalk(self):print("走路")實體方法的使用方式大家可以看到上面的Person類別。
我們建立了一個「人」的類別,在人這個類別裡面,我們設定instance_method方法,這個方法即為實體方法,會傳遞物件本身作為第一個參數。
我們可以對Person類別進行下面的操作。
classPerson:#實體方法definstance_method(self):print(f'typeis:{type(self)}\\nidis:{id(self)}')returnselfJohn=Person()John.instance_method()會得到下面的結果:實體方法透過self參數可以自由的存取物件的屬性及其他方法,藉此來改變物件的狀態,我們將上面的Person類別修改如下:#類別classPerson:#屬性def__init__(self):self.last_name='Lennon'#實體方法defwalk(self):print(f"{self.last_name}正在走路")John=Person()John.walk()這時候透過John.walk(),就可以存取物件的last_name屬性Lennon。
因此,執行結果會是Lennon正在走路。
另外,在實體方法中,我們可以透過self.__class__屬性來存取或改變類別Class本身的狀態。
#類別classPerson:#類別變數meals=3#屬性def__init__(self):self.last_name='Lennon'#實體方法defwalk(self):print(f"{self.last_name}正在走路")defget_fat(self):self.__class__.meals=4John=Person()John.get_fat()print(f"每天吃{Person.meals}餐")以上面的程式碼來說,我們在自訂的get_fat方法裡面透過self.__class__屬性來改變類別中meals的狀態。
因此,程式的執行結果會是『每天吃4餐』。
從這個角度來看,實體方法的權限實在是很大。
StaticMethod靜態方法在一般的情況下,我們需要先透過類別實體化建立物件後,才可以呼叫方法。
但是,靜態方法提供我們在沒有建立實體化物件的情況下也可以呼叫它。
使用靜態方法需要透過修飾器@staticmethod。
另一個與一般實體方法不同的是,靜態方法不會傳遞物件本身(self)作為第一個參數,它只能處理使用者傳入的參數。
靜態方法的使用方式以下面的例子來說,run為靜態方法。
我們在defrun的上方加上修飾器@staticmethod,並且在run的後面放置一個沒有self的括號。
#類別classPerson:#靜態方法@staticmethoddefrun():print("跑步吧!")John=Person()John.run()當然,靜態方法雖不需要self,卻可以接受其他任意的參數。
也因此靜態方法無法改變類別(Class)以及物件的狀態。
#類別classPerson:#靜態方法@staticmethoddefrun(time,distance):print(f"{time}跑了{distance}公尺!")John=Person()John.run("今天",5000)由於靜態方法無法改變類別(Class)以及物件的狀態,因此通常會使用在不需要存取物件屬性或方法的時候。
例如上面的程式碼,我們將靜態方法run進行修改,加入兩個參數time與distance。
執行程式後會得到「今天跑了5000公尺!」的結果。
ClassMethod類別方法類別方法一樣提供我們在沒有建立實例化物件的情況下可以呼叫它。
但與靜態方法不同的地方是,類別方法會傳遞類別本身(cls)作為第一個參數。
使用類別方法需要透過修飾器@classmethod。
classPerson:@classmethoddefaclassmethod(cls):print(cls)print(f'typeis:{type(cls)}\\nidis:{id(cls)}')Person.aclassmethod()會得到下面的結果:不同於實體方法的self參數會指向物件本身,類別方法的cls參數,會指向類別(Class)本身。
因此,類別方法不能修改以該類別建立出來的物件,類別方法只能夠改變類別(Class)本身的狀態,在使用上要特別注意。
雖說類別方法無法直接改變物件的狀態,但實際上類別方法可以透過改變類別(Class)本身的狀態,進而間接的影響該類別建立出來物件。
類別方法有能力存取類別的狀態或方法。
另外,類別方法也可以做為操控類別變數(classvariable)與做為建構子(Constructor)的替代與補充。
類別方法的使用方式例如,假設我們有一家手搖飲品店,需要製作各種不同品項的飲料。
這時候可以拿類別方法當成工廠函式(factoryfunction)來生產出各種不同的品項:classDrinks:def__init__(self,name,materials):self.name=nameself.materials=materialsdef__repr__(self):returnf'{str(self.name)}材料:{str(self.materials)}'#returnf'Drinks({self.materials})'@classmethoddefmilk_tea(cls):returncls('奶茶',['牛奶','紅茶'])@classmethoddefpearl_milk_tea(cls):returncls('珍珠奶茶',['牛奶','紅茶','珍珠'])@classmethoddefjasmine_green_tea(cls):returncls('茉莉綠茶',['茉莉花','綠茶'])#印出成分print(Drinks.milk_tea())print(Drinks.pearl_milk_tea())print(Drinks.jasmine_green_tea())在上面的程式裡,我們在milk_tea、pearl_milk_tea與jasmine_green_tea方法裡面使用的是cls參數,而不是一般常用的self參數。
執行結果如下:使用這種方式,我們可以依照市場需要隨時增加特定口味的飲料品項而不需要「回過頭」去修改類別的屬性,好處是程式碼會比較『乾』(DRY=Don’tRepeatYourself)。
例:合併使用類別方法與靜態方法下面的例子合併使用了類別方法與靜態方法。
類別Person有兩個屬性name(姓名)與age(年齡)。
我們藉由讓使用者輸入自己的姓名與出生日期,給程式計算使用者的年齡並且判斷該年齡是否已成年後,最後透過print顯示在螢幕上。
fromdatetimeimportdate#類別classPerson:#屬性def__init__(self,name,age):self.name=nameself.age=age#類別方法@classmethoddefbirth_year(cls,name,b_year):age=date.today().year-b_yearreturncls(name,age)#靜態方法@staticmethoddefisAdult(age):ifage>=18:return'已成年'else:return'未成年'John=Person.birth_year('John',2003)print(f'{John.name},{John.age}歲{Person.isAdult(John.age)}')執行後會得到下面的結果:透過這種方式,我們可以未來可以重複使用birth_year方法,來將年轉換為歲數,而isAdult方法,則可以用來判斷某個數字是否大於等於18。
這樣子處理是不是覺得比較簡潔方便?self與cls值得一提的是,在習慣上我們會以self作為命名,代表物件本身的參數。
而會以cls作為命名,代表類別本身的參數。
若您想使用別的名稱作為代表,並非不可,只要它們必須當成物件與類別的第一個參數。
只不過如此一來其他工程師恐怕較難理解您的程式碼。
結語綜合上述,實體方法(InstanceMethod)可以存取物件實體,是最常用的方法。
類別方法(ClassMethod)可以存取類別,可以呼叫類別本身,用來製作替代的建構子。
而靜態方法(StaticMethod)無法存取物件與類別,它獨立於物件或類別以外。
使用靜態方法與類別方法可以讓我們清楚的區分出類別的架構中「可以改變」與「不可以改變」的範圍。
避免在無意之間越過了界線,產生不容易找不到的程式臭蟲(bug)。
只要能夠明白這些方法的差異,在撰寫Python物件導向(Object-orientedPython)程式的時候,就可以清楚的表達目的。
程式碼也會比較容易維護。
MorefromPythonEverywhere-fromBeginnertoAdvancedThisplaceisAllaboutPython.FromBeginnertoAdvancedprograming,byusingPython,youcandoanythingyouimagine.ReadmorefromPythonEverywhere-fromBeginnertoAdvancedAboutHelpTermsPrivacyGettheMediumappGetstartedSeanYeh420Followers#Taipei,InternetDigitalAdvertising「樂於發現與分享,才是最大贏家」FollowHelpStatusWritersBlogCareersPrivacyTermsAboutKnowable
延伸文章資訊
- 1Python 入門指南- 單元9 - 類別 - 程式語言教學誌
類別(class) 用來設計自己需要的物件(object) ,也就是說類別是物件的藍圖。 Python 中設計類別使用關鍵字(keyword) class ,裡頭可定義類別的類別屬性(class...
- 2[Python物件導向]淺談Python類別(Class) - Learn Code With Mike
在學習程式語言時,或多或少都有聽過物件導向程式設計(Object-oriented programming,簡稱OOP),它是一個具有物件(Object)概念的開發方式,能夠提高軟體的重用性、擴...
- 3淺談Python類別(Class) - 104學習精靈
Q:什麼是類別(Class)? 簡單來說,就是物件(Object)的藍圖(blueprint)。就像要生產一部汽車時,都會有設計圖,藉此可以知道此類汽車會有哪些特性及功能 ...
- 4Day21 python基礎(五)-class類別 - iT 邦幫忙
python是一種物件導向的程式設計而要使用物件導向設計就要對於類別及物件有基本的 ... class user: def __init__(self,name,sex,age): self.n...
- 5[Python物件導向]解析Python物件導向設計的3種類型方法 ...
實體方法(Instance Method) · 類別方法(Class Method) · 靜態方法(Static Method) ...