例項方法

在類中定義的方法預設都是例項方法,前面幾篇文章已經大量使用到例項方法

例項方法栗子

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