例項方法
在類中定義的方法預設都是例項方法,前面幾篇文章已經大量使用到例項方法
例項方法栗子
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 的實際應用場景
可以參考這篇文章
待我實戰後再來完善此章節
https://www.zhihu.com/question/20021164