Python – 面向對象編程 – 實例方法、靜態方法、類方法
- 2021 年 8 月 29 日
- 筆記
- Python, 測試進階知識系列 - Python
實例方法
在類中定義的方法默認都是實例方法,前面幾篇文章已經大量使用到實例方法
實例方法栗子
class PoloBlog: def __init__(self, name, age): print("自動調用構造方法") self.name = name self.age = age def test(self): print("一個實例方法,需要通過對象調用") print("my name is :", self.name, " and my age is :", self.age) blog = PoloBlog("小菠蘿", 24) blog.test() # 輸出結果 自動調用構造方法 一個實例方法,需要通過對象調用 my name is : 小菠蘿 and my age is : 24
- 最少也要包含一個 self 參數,用於綁定調用此方法的實例對象(Python 會自動完成綁定)
- 實例方法通常會用實例對象直接調用
通過類名調用實例方法
Python 也支援通過類名調用實例方法,但需要手動給 self 參數傳實例對象
blog = PoloBlog("小菠蘿", 24) PoloBlog.test(blog) # 輸出結果 自動調用構造方法 一個實例方法,需要通過對象調用 my name is : 小菠蘿 and my age is : 24
假設不傳實例對象,pycharm 會有warning
類方法
類方法和實例方法很相似,又很不相似
相似點
- 也至少要包含一個參數,不過通常命名為 cls
- 在調用類方法時,無需顯式為 cls 參數傳參,但傳遞的並不是實例對象,而是類對象本身
不同點
最大的不同在於需要使用 @classmethod 裝飾器才能稱為類方法
實際栗子
class PoloBlog: # 類屬性 sum = 0 # 類方法, 添加裝飾器 @classmethod def class_func(cls): print("class_func cls 對象的 id ", id(cls)) cls.sum += 1 print("類屬性 sum ", cls.sum) @classmethod def class_func_twi(cls): print("class_func_twi cls 對象的 id ", id(cls)) cls.sum += 1 print("類屬性 sum ", cls.sum) PoloBlog.class_func() PoloBlog.class_func_twi() # 輸出結果 class_func cls 對象的 id 140583542774880 類屬性 sum 1 class_func_twi cls 對象的 id 140583542774880 類屬性 sum 2
cls 代表的是同一個對象,類對象
類方法可以調用實例方法嗎?
可以,但有局限性
class PoloBlog: # 類屬性 sum = 0 def __init__(self, sum): self.sum = sum # 實例方法 def test(self): print("self id is ",id(self)) print("self 對象的 sum 屬性值為:", self.sum) # 類方法, 添加裝飾器 @classmethod def class_func(cls): print("cls id is ", id(cls)) print("類屬性 sum ", cls.sum) # 調用實例方法 cls.test(cls) PoloBlog.class_func() # 輸出結果 cls id is 140500501817184 類屬性 sum 0 self id is 140500501817184 self 對象的 sum 屬性值為: 0
- 類方法調用實例方法的方式: cls.實例方法(cls) ,通過 cls 調用,且還要傳遞 cls 為參數
- 從 id 相同即可看出,實例方法接收的仍然是一個類對象
實例對象可以調用類方法嗎?
可以,但不建議
blog = PoloBlog(2) blog.class_func() # 輸出結果 cls id is 140500501817184 類屬性 sum 0 self id is 140500501817184 self 對象的 sum 屬性值為: 0
- blog 是一個實例對象,且初始化賦值了 sum 實例屬性
- 但最後實例方法列印的仍然是 sum 類屬性,表明類方法無法訪問實例屬性
- 且 cls、self 參數的 id 和上面的栗子完全一樣,表明即使通過實例對象調用類方法,傳遞的仍然是類對象的引用,所有類方法都被同一個類對象調用,一個類只有一個類對象
實例方法可以調用類屬性嗎?
可以,但不能通過實例對象調用,只能通過類對象
class PoloBlog: # 類屬性 name = "類啊類屬性" def __init__(self, name): self.name = name # 實例方法 def test(self): # 錯誤栗子 # print(name) # 訪問的仍然是實例屬性 print(self.name) # 通過類名訪問 print(PoloBlog.name) blog = PoloBlog("小菠蘿") blog.test() # 輸出結果 小菠蘿 類啊類屬性
假設直接調用 name 變數可以嗎
肯定不行,報錯
擴展思考題!
- 一個方法內部既需要訪問實例屬性,又需要訪問類屬性,應該定義為什麼方法?
- 答案:實例方法,因為可以通過 類對象.類屬性 來訪問,但在類方法中無法訪問實例屬性
程式碼栗子直接看上面一個就是啦!
靜態方法
- 和之前學過的函數一毛一樣,唯一區別是:靜態方法需要定義在類體中,且需要添加 @staticmethod 裝飾器
- 靜態方法沒有 self、cls 參數,也不需要至少傳一個參數,和普通函數一樣
- Python 解釋器不會對它包含的參數做任何類或對象的綁定,所以靜態方法無法調用任何類屬性、類方法、實例屬性、實例方法,除非通過類名和實例對象
class PoloBlog: # 靜態方法 @staticmethod def info(name, age): print(name, age) # 通過類對象調用 PoloBlog.info("小菠蘿111", 24) blog = PoloBlog() # 通過實例對象調用 blog.info("小菠蘿222", 14) # 輸出結果 小菠蘿111 24 小菠蘿222 14
關於 classmethod 和 staticmethod 的實際應用場景
可以參考這篇文章
待我實戰後再來完善此章節
//www.zhihu.com/question/20021164