Python類定義中的@classmethod(類方法)和@staticmethod(靜態方法)的使用
之前的一篇博文詳細講解了什麼函式裝飾器(Python迭代器、生成器、裝飾器的使用)。在類的定義中,我們也常常見到裝飾器的使用,並且最常用的就是@classmethod,@staticmethod來裝飾我們自定義類的函式(方法),這兩個內建的裝飾器是什麼作用呢?
在講解這兩種方法前我們需要只要,一般我們在類當中定義的方法都是例項方法,定義中都需要帶有self關鍵字,要使用例項方法,必須先把我們的類例項化才能使用。比如下面的個Dog類中的name方法。
class Dog(): def __init__(self, name, age): self.name = name self.age = age def dogname(self): print("我是一隻狗,名叫{}".format(self.name)) dog1 = Dog("阿黃", 12)
如果要使用例項方法dogname(),我們只能採用dog1.dogname()才能夠使用。例項方法可以訪問例項變數、類變數,使用時必須通過例項名來呼叫。
1、類方法(@classmethod)
什麼叫做類方法呢?只要是在定義函式的時候在前面加上@classmethod那麼接下來定義的這個函式就被稱為類方法。
class Dog(): dog_dict = {"大狗":12, "二狗":11, "三狗":20} # 定義了一個類變數(一個字典),表示大狗有12只,二狗有11只,三狗有20只 def __init__(self, name, age): self.name = name self.age = age def dogname(self): print("我是一隻狗,名叫{}".format(self.name)) @classmethod def dog_number(cls): number = 0 for item in cls.dog_dict.items(): number += item[1] print('總共有{}只狗'.format(number)) dog1 = Dog("阿黃", 12) dog2 = Dog("二黃", 7) dog1.dog_number() Dog.dog_number()
執行結果:
類方法不是因為具體的哪個例項而改變,因此在定義時必須使用cls(類變數)作為第一個引數(大家可以看成self的作用,只是它表示的是一個類)。既然這個方法是類方法,那我們自然可以採用類名.dog_number()來進行呼叫,也可以採用例項名.dog_number()來進行呼叫。類方法是可以訪問類變數,當然也可以訪問例項變數(不過需要傳入引數self,並且在使用時需要把例項名傳入函式中)。
2、靜態方法(@staticmethod)
同樣的在定義函式的時候在前面加上@staticmethod那麼接下來定義的這個函式就被稱為靜態方法,靜態方法不要求你強制傳入任何引數(例項方法必須傳入slef,類方法必須傳入cls),因此這個函式對類變數和例項變數都是一無所知,你需要自己傳入引數才能使用。呼叫的時候,可以使用例項名.方法名呼叫,或者類名.方法名呼叫。看例子
class Dog(): dog_dict = {"大狗":12, "二狗":11, "三狗":20} # 定義了一個類變數(一個字典),表示大狗有12只,二狗有11只,三狗有20只 def __init__(self, name, age): self.name = name self.age = age def dogname(self): print("我是一隻狗,名叫{}".format(self.name)) @classmethod def dog_number(cls): number = 0 for item in cls.dog_dict.items(): number += item[1] print('總共有{}只狗'.format(number)) @staticmethod def total_age(dogs): ''' 傳入一個Dog例項的list,並計算這些狗的總年齡 ''' total = 0 for dog in dogs: total += dog.age return total dog1 = Dog("阿黃", 12) dog2 = Dog("二黃", 7) print(dog1.total_age([dog1, dog2]))
3、額外知識
1、類變數:是所有例項共享的,專屬於這個類的,換句話說只要當前這個例項時屬於A類,那麼該例項就能使用A類的所有類變數。訪問類變數得分情況,如果是在類方法中訪問類變數,那麼是使用cls.類變數名;如果是在例項方法中訪問類變數,使用slef.類變數名。
2、除了常用的@classmethod和@staticmethod是常用的自定義類函式的裝飾器,還有@property 也是常用的裝飾類函式的裝飾器,其作用是可以直接使用例項名.函式名來進行呼叫函式,不需要末尾加()了。