classmethod()方法返回給定函數(shù)的類方法。
classmethod()方法的語(yǔ)法為:
classmethod(function)
classmethod()被認(rèn)為是不符合Python規(guī)范的,所以在較新的Python版本中,可以使用@classmethod裝飾器來(lái)定義類方法。
語(yǔ)法為:
@classmethod def func(cls, args...)
classmethod()方法采用一個(gè)參數(shù):
function-需要轉(zhuǎn)換為類方法的函數(shù)
classmethod()方法返回給定函數(shù)的類方法。
類方法是綁定到類而不是對(duì)象的方法。它不需要?jiǎng)?chuàng)建類示例,就像classmethod(靜態(tài)方法)一樣。
靜態(tài)方法和類方法之間的區(qū)別是:
靜態(tài)方法對(duì)類一無(wú)所知,只處理參數(shù)
類方法與類一起使用,因?yàn)槠鋮?shù)始終是類本身。
類方法可以由類及其對(duì)象調(diào)用。
Class.classmethod() Or even Class().classmethod()
但是無(wú)論如何,類方法始終附加到具有第一個(gè)參數(shù)的類,因?yàn)轭惐旧頌?var>cls。
def classMethod(cls, args...)
class Person: age = 25 def printAge(cls): print('年齡是:', cls.age) # create printAge class method Person.printAge = classmethod(Person.printAge) Person.printAge()
運(yùn)行該程序時(shí),輸出為:
年齡是: 25
在這里,我們有一個(gè)class Person,其成員變量age被指定為25。
我們還有一個(gè)函數(shù)printAge,它只接受一個(gè)參數(shù)cls,而不是我們通常使用的self。
cls接受類Person作為參數(shù),而不是Person的對(duì)象/示例。
現(xiàn)在,我們將該方法Person.printAge作為參數(shù)傳遞給該函數(shù)classmethod。這會(huì)將方法轉(zhuǎn)換為類方法,以便它接受第一個(gè)參數(shù)作為類(即Person)。
在最后一行中,調(diào)用時(shí)printAge沒(méi)有像靜態(tài)方法那樣創(chuàng)建Person對(duì)象。這將打印類變量age。
工廠方法是那些針對(duì)不同用例返回類對(duì)象(如構(gòu)造函數(shù))的方法。
它類似于C ++中的函數(shù)重載。由于Python沒(méi)有這樣的功能,因此使用了類方法和靜態(tài)方法。
from datetime import date # random Person class Person: def __init__(self, name, age): self.name = name self.age = age @classmethod def fromBirthYear(cls, name, birthYear): return cls(name, date.today().year - birthYear) def display(self): print(self.name + "'s age is: " + str(self.age)) person = Person('Adam', 19) person.display() person1 = Person.fromBirthYear('John', 1985) person1.display()
運(yùn)行該程序時(shí),輸出為:
Adam's age is: 19 John's age is: 31
在這里,我們有兩個(gè)類示例創(chuàng)建者,一個(gè)構(gòu)造函數(shù)和一個(gè)fromBirthYear方法。
構(gòu)造函數(shù)采用常規(guī)參數(shù)name和age。而fromBirthYear采用cls,name和birthYear,通過(guò)用當(dāng)前年份減去當(dāng)前年齡來(lái)計(jì)算當(dāng)前年齡,并返回類示例。
fromBirthYear方法將Person類(不是Person對(duì)象)作為第一個(gè)參數(shù)cls,并通過(guò)調(diào)用返回構(gòu)造函數(shù)cls(name, date.today().year - birthYear),這等效于Person(name, date.today().year - birthYear)
在該方法之前,我們看到了@classmethod。這稱為裝飾器,用于轉(zhuǎn)換fromBirthYear為classmethod()的類方法。
每當(dāng)將工廠方法實(shí)現(xiàn)為類方法來(lái)派生一個(gè)類時(shí),它都可以確保正確創(chuàng)建派生類的示例。
您可以為上面的示例創(chuàng)建一個(gè)靜態(tài)方法,但是它創(chuàng)建的對(duì)象將始終被硬編碼為Base類。
但是,當(dāng)您使用類方法時(shí),它將創(chuàng)建派生類的正確示例。
from datetime import date # random Person class Person: def __init__(self, name, age): self.name = name self.age = age @staticmethod def fromFathersAge(name, fatherAge, fatherPersonAgeDiff): return Person(name, date.today().year - fatherAge + fatherPersonAgeDiff) @classmethod def fromBirthYear(cls, name, birthYear): return cls(name, date.today().year - birthYear) def display(self): print(self.name + "'s age is: " + str(self.age)) class Man(Person): sex = 'Male' man = Man.fromBirthYear('John', 1985) print(isinstance(man, Man)) man1 = Man.fromFathersAge('John', 1965, 20) print(isinstance(man1, Man))
運(yùn)行該程序時(shí),輸出為:
True False
在這里,使用靜態(tài)方法創(chuàng)建類示例需要我們?cè)趧?chuàng)建過(guò)程中對(duì)示例類型進(jìn)行硬編碼。
這顯然會(huì)導(dǎo)致一個(gè)問(wèn)題,當(dāng)Person來(lái)繼承Man時(shí)。
fromFathersAge方法不返回Man對(duì)象,而是其基類Person的對(duì)象。
這違反了OOP范式。使用類方法fromBirthYear可以確保代碼的面向?qū)ο螅驗(yàn)樗鼘⒌谝粋€(gè)參數(shù)作為類本身并調(diào)用其工廠方法。