飛酷告訴你@classmethod類(lèi)方法的作用原來(lái)那么大
2024-06-12 加入收藏
大家好,我是小K,今天由我來(lái)為大家講解類(lèi)方法和類(lèi)方法的使用場(chǎng)景。
什么是類(lèi)方法?
要說(shuō)什么是類(lèi)方法,就肯定要先說(shuō)下什么是類(lèi),什么是方法。(廢話(huà))
類(lèi)
用來(lái)描述具有相同的屬性和方法的對(duì)象的集合。
它定義了該集合中每個(gè)對(duì)象所共有的屬性和方法。
對(duì)象是類(lèi)的實(shí)例。
方法
類(lèi)中定義的函數(shù)。
這里方法是指所有定義在類(lèi)里面的方法,包含實(shí)例方法、靜態(tài)方法、類(lèi)方法。
但我們今天所說(shuō)的類(lèi)方法并不是類(lèi)+方法,而是類(lèi)里面方法的一種。
類(lèi)方法
修飾器@classmethod
來(lái)標(biāo)識(shí)其為類(lèi)方法,第一個(gè)參數(shù)必須要默認(rèn)傳類(lèi),一般習(xí)慣用cls
(表示類(lèi)本身)。
類(lèi)方法是只與類(lèi)本身有關(guān)而與實(shí)例無(wú)關(guān)的方法。
通過(guò)cls
引用的必定是類(lèi)對(duì)象的屬性和方法,不能訪問(wèn)實(shí)例屬性,能夠通過(guò)實(shí)例對(duì)象和類(lèi)對(duì)象去訪問(wèn)類(lèi)方法。
代碼示例:
class MyClass:
counter = 0 # 類(lèi)屬性
@classmethod
def increment(cls):
cls.counter += 1
# 調(diào)用類(lèi)方法
MyClass.increment()
print(MyClass.counter) # 輸出 1
上述代碼中我們不需要實(shí)例化MyClass
就可執(zhí)行類(lèi)中的increment
函數(shù),還可以拿到/修改類(lèi)屬性的值。
所以這對(duì)于管理類(lèi)級(jí)別的狀態(tài)是非常有用的。
類(lèi)方法的用處
1. 工廠方法
類(lèi)方法可以用作工廠函數(shù),創(chuàng)建類(lèi)的實(shí)例并返回。
class Person:
def __init__(self, name, age):
self.name = name
self.age = age
@classmethod
def create_person(cls, name, birth_year):
age = datetime.now().year - birth_year
return cls(name, age)
# 使用類(lèi)方法創(chuàng)建實(shí)例
person = Person.create_person("John", 1990)
用當(dāng)前年份減去出生年份來(lái)計(jì)算年齡(age),然后使用這些信息創(chuàng)建并返回一個(gè)新的Person類(lèi)實(shí)例。
2. 提供備用構(gòu)造函數(shù)
類(lèi)方法允許提供不同的構(gòu)造方式,以滿(mǎn)足不同的需求。
class Point:
def __init__(self, x, y):
self.x = x
self.y = y
@classmethod
def from_tuple(cls, point_tuple):
return cls(*point_tuple)
# 使用類(lèi)方法創(chuàng)建實(shí)例
point = Point.from_tuple((3, 4))
3. 多線程鎖
在多線程環(huán)境中,類(lèi)方法可以與鎖一起使用,確保對(duì)共享資源的訪問(wèn)是線程安全的,防止競(jìng)爭(zhēng)條件和數(shù)據(jù)不一致
import threading
class Counter:
count = 0
lock = threading.Lock()
@classmethod
def increment(cls):
with cls.lock:
cls.count += 1
# 在多線程環(huán)境中安全地增加計(jì)數(shù)
def worker():
for _ in range(100000):
Counter.increment()
# 創(chuàng)建多個(gè)線程來(lái)執(zhí)行工作
threads = [threading.Thread(target=worker) for _ in range(5)]
# 啟動(dòng)線程
for thread in threads:
thread.start()
# 等待所有線程完成
for thread in threads:
thread.join()
# 輸出最終的計(jì)數(shù)值
print(Counter.count)
只有用類(lèi)方法拿到鎖,才允許進(jìn)行
count += 1
的操作。
最后
相比實(shí)例方法,類(lèi)方法是一個(gè)很容易被忽略的知識(shí)點(diǎn),很多入門(mén)書(shū)里并不會(huì)以此為重點(diǎn)去講解它的用途和特點(diǎn)。
但在一些處理與整個(gè)類(lèi)相關(guān)的任務(wù),使用類(lèi)方法還是一個(gè)非常明智的選擇。