前言
python 類里面常用的方法有3個:靜態方法(@staticmethod),類方法(@classmethod)和實例方法(self)
本篇講解這3種方法在使用上有什么區別。
函數
先從函數說起,方法跟函數是有區別的,經常有人容易混淆,函數定義是def 關鍵字定義(外面沒class)
def fun():
a = "hello"
return a
# 函數調用
res = fun()
print(res)
函數調用使用函數名稱后面加括號就能調用了
實例方法(self)
類里面的方法定義也是用def 關鍵字,注意在類里面叫方法了,不叫函數,定義的方法默認在括號里面加一個self參數。
self 是類本身的實例對象,所以在看到def 定義的方法括號后面有self參數的叫實例方法。
class A(object):
count = 0
def fun(self):
b = "world"
return b
# A類不能直接調用fun
# print(A.fun())
a = A()
print(a.fun())
前面https://www.cnblogs.com/yoyoketang/p/15151723.html講屬性的時候說到過A類的屬性和A()實例對象屬性是不一樣的。
fun()里面帶了self參數,那么它是實例方法,也就是A()實例對象的方法了,所以必須先實例化A()才能調用此方法。
靜態方法(@staticmethod)
我們可以在函數里面寫一個類
def fun():
a = "hello"
class A(object):
count = 0
def fun(self):
b = "world"
return b
return A
於是會想到,在類里面是不是也可以寫一個函數呢?於是就有了靜態方法(@staticmethod),靜態方法的出現就是為了在類里面可以寫一個函數,當普通的函數去調用。
定義靜態方法需使用@staticmethod裝飾器,並且括號后面不需要self參數了。
# 作者-上海悠悠 QQ交流群:717225969
# blog地址 https://www.cnblogs.com/yoyoketang/
class A(object):
count = 0
def fun(self):
b = "world"
return b
@staticmethod
def start():
print("start-----")
# 不用實例化也能調用
A.start()
# 實例化也能調用
a = A()
a.start()
靜態方法不需要實例化可以直接調用,實例化后也能調用,可以理解成函數。
類方法(@classmethod)
類里面有2個概念,屬性和方法。
前面講到A類和A()實例對象的屬性是不一樣的,比如
- A類只要count屬性
- A()實例對象的屬性是
__init__
里面的age和name,並且包含A類屬性count
class A(object):
count = 0
def __init__(self):
self.age = 18
self.name = "yoyo"
# A只有count屬性
print(A.count)
# A() 實例化對象
a = A()
print(a.count)
print(a.name)
print(a.age)
既然已經知道了A類的屬性和A()實例對象屬性是不一樣的,再回到前面的實例方法概念上,實例方法是A()實例對象的方法。
既然A()實例對象有實例方法,那么A類當然也有類方法的概念了,於是可以在方法上加上@classmethod裝飾器聲明它是類方法,並且括號第一個參數cls是指類本身
# 作者-上海悠悠 QQ交流群:717225969
# blog地址 https://www.cnblogs.com/yoyoketang/
class A(object):
count = 0
def fun(self):
b = "world"
return b
@staticmethod
def start():
print("start-----")
@classmethod
def create(cls):
print("create--------")
# 不需要實例化,類名稱直接調用類方法
A.create()
# 實例化也能調用類方法
a = A()
a.create()
類方法使用場景
實例方法和靜態方法小伙伴們應該是經常用的,類方法這個概念本身比較難懂,就算看懂了也不知道如何用到具體場景上,在網上搜到一個案例講解的挺好的。
看下面的定義的一個時間類:
class DataTest(object):
day = 0
month = 0
year = 0
def __init__(self, year=0, month=0, day=0):
self.day = day
self.month = month
self.year = year
def out_date(self):
print("year :", self.year)
print("month :", self.month)
print("day :", self.day)
t = DataTest(2021, 8, 18)
t.out_date()
輸出:
year : 2021
month : 8
day : 18
如果用戶輸入的是 "2016-8-1" 這樣的字符格式,那么就需要調用Date_test 類前做一下處理:
string_date = '2018-8-18'
year, month, day = map(int, string_date.split('-'))
s = DataTest(year, month, day)
print(s.out_date())
先把‘2018-8-18’ 分解成 year,month,day三個變量,然后轉成int,再調用DataTest(year, month, day) 也很符合期望。
那我可不可以把這個字符串處理的函數放到 DateTest 類當中呢?
那么@classmethod 就開始出場了
class DataTest(object):
day = 0
month = 0
year = 0
def __init__(self, year=0, month=0, day=0):
self.day = day
self.month = month
self.year = year
def out_date(self):
print("year :", self.year)
print("month :", self.month)
print("day :", self.day)
@classmethod
def get_data(cls, string_date):
"""處理'2018-8-18'字符格式"""
year, month, day = map(int, string_date.split('-'))
return cls(year, month, day)
定義一個get_data類方法,處理完字符串后返回這個類的實例對象
r = DataTest.get_data('2018-8-18')
r.out_date()
這樣同樣可以達到實例化的效果,於是就兼容了前面的代碼了
參考資料https://www.zhihu.com/question/20021164