假如今晚沒有夢到更多封裝主題,本篇應該是這條物件導向大支柱的最後一講了。
類別屬性
(class attributes)和實例屬性
(instance attributes)兩種。同樣地,方法(methods)也有類別方法
class methods和實例方法
instance methods兩種。static methods
,中文稱為「靜態方法」(註1)。我們在做某個專案。為了需要撰寫get_total_species()
和get_total_trees()
兩個函數,分別取得全球的樹種數及全球有多少棵樹。先不管函數內用甚麼方式取得,這不是今天要說的重點。
另外又寫了一個通用型的判斷樹木健康程度的函數get_health_status()
,傳入某些病菌的單位數量,傳回樹木健康程度字串。請別和筆者爭辯:不可能用同一標準去衡量不同樹木的健康狀況。筆者當然知道。這個方法只為程式講解而假設出來,和植物學專業毫無關係。
這三個函數當然可以成為獨立於任何類別之外的普通函數。但我們再想,專案中本來就有一個Tree()類別,也許把所有和「樹」有關的函數通通納入Tree()類別內,更符合物件導向的精神。
不過,這三個函數其實並沒有使用任何Tree()類別內的資源(即屬性/方法),在類別中的地位較為特殊。
這三個就是靜態方法。
類別的設計如下,略去了一些和靜態方法無關的code:
class Tree():
__count = 0
def __init__(self, breed: str, age: int): # constructor
self.__breed = breed
self.__age = age
Tree.__count += 1
@classmethod
@property
def count(cls) -> int:
'''The __count property(getter).'''
return cls.__count
@property
def breed(self) -> str:
'''The breed property(getter).'''
return self.__breed
@property
def age(self) -> int:
'''The age property(getter).'''
return self.__age
@staticmethod # static method要加這個decorator。
def get_total_species(): # 這個就是static method。
# 經過某些計算,或者連上某個API網站取得全球總樹種數目。
total_species = 73_000 # 這是假設值。
return total_species
@staticmethod
def get_total_trees(): # 注意:static method沒有self或cls參數。
# 經過某些計算,或者連上某個API網站取得全球總共有多少棵樹。
total_trees = 3_040_000_000_000 # 這是假設值。
return total_trees
@staticmethod
def get_health_status(germs): # 這個就是static method。
health_table = ((0, 1_500, 'healthy'), (1_501, 30_000, 'infected'), (30_000, 100_000, 'seriously ill'), (100_001, 9**999, 'dying'))
for min_, max_, status in health_table:
if min_ <= germs <= max_:
return status
測試程式:
print(f'{Tree.get_total_species()=:,}')
print(f'{Tree.get_total_trees()=:,}')
print(f'{Tree.get_health_status(50_000)=}')
輸出:
@staticmethod
裝飾器包裝。這個裝飾器和之前講過的@property
及classmethod
一樣,都是Python內設,直接拿來用就行,不必import甚麼模組。類別.方法()
或物件.方法()
兩種方式都可以呼叫靜態方法。不過筆者認為類別.方法()
比較合理。靜態方法本來就屬於整個類別,和物件無關,即使未建立任何物件也可以使用。self
也不是cls
。事實上靜態方法根本「不能有」self
或cls
。原因為:static methods不會接收隱藏的第一個參數。self
或cls
,靜態方法無法存取類別內的任何屬性,也不能呼叫類別的任何方法,連其他靜態方法也沒法呼叫。靜態方法是「獨善其身」。cls
)self
)cls
也無self
)註1: C++, Java, C#等物件導向程式語言也有static methods(或稱static member function)。不過意義和Python的static methods不盡相同。