Python v3.7.0
靜態方法
靜態方法實際就是類中的一個普通函數。主要是用來存放邏輯性的代碼,邏輯上屬於類,但是和類本身沒有關係,也就是說在靜態方法中,不會涉及到類中的屬性和方法的操作。可以理解爲,靜態方法是個獨立的、單純的函數,它僅僅託管於某個類的名稱空間中,便於使用和維護。
通常情況下,靜態方法使用@staticmethod
裝飾器(或使用staticmethod()
)來聲明。如下面的例子:
import time
class TimeTest():
def __init__(self, hour, minute, second):
self.hour = hour
self.minute = minute
self.second = second
@staticmethod
def show_time():
return time.strftime('%H:%m:%s', time.localtime())
if __name__ == '__main__':
# 下面兩種方式都可以正確調用
print(TimeTest.show_time())
print(TimeTest(1, 0, 0).show_time())
運行結果爲:
20:04:1555158168
20:04:1555158168
在Python 3中,如果一個類的方法沒有self參數,不再需要必須聲明爲靜態方法,但是這樣的話只能通過類去調用這個方法,如果通過實例對象調用這個方法就會引發異常。
class Animal(object):
# @staticmethod
def greet():
pass
if __name__ == '__main__':
# 以下調用方式會報錯
Animal().greet()
異常信息:
TypeError: greet() takes 0 positional arguments but 1 was given
這是因爲greet
方法沒有聲明爲靜態方法,類實例在調用此方法時,會將self
參數傳入到方法中,而方法本身不接受任何參數,從而引發異常。
類方法
定義類方法需要使用裝飾器@classmethod
(或使用classmethod()
),傳入的第一個參數必須爲必須是當前類對象,該參數名一般約定爲“cls”,通過它來傳遞類的屬性和方法cls(不能傳實例的屬性和方法)。
類方法可以通過類直接調用,也可以通過實例直接調用。但無論哪種調用方式,第一個參數一定是類本身。
class Persion(object):
@classmethod
def treasure(cls):
print(__name__, type(cls), cls, sep='||')
if __name__ == '__main__':
# 類對象和實例對象都可以調用
Persion.treasure()
Persion().treasure()
運行結果爲:
__main__||<class 'type'>||<class '__main__.Persion'>
__main__||<class 'type'>||<class '__main__.Persion'>
從運行結果可以看出,無論是通過類調用還是實例調用,類方法都能正常工作。且通過打印cls,可以看出cls傳入的都是類實例本身。
這裏需要注意,如果存在類的繼承,那類方法獲取的類是類樹上最底層的類。如下,Someone類的treasure繼承自Persion類,但是從最後的運行結果中可以看到,方法運行時傳入的類是Someone,而非其父類。
class Someone(Persion):
pass
if __name__ == '__main__':
Someone.treasure()
Someone().treasure()
運行結果:
<class '__main__.Someone'>
<class 'type'> <class '__main__.Someone'>
實例方法
實例方法第一個參數必須是實例對象本身,該參數名一般約定爲“self”,通過它來傳遞實例對象的屬性和方法(也可以傳類的屬性和方法)。
實例方法在調用的時候,self 是自動傳遞的,所以不需要我們再處理,但如果使用類對象直接調用實例方法,則需要顯式地將實例作爲參數傳入。
class Test(object):
def __init__(self, name):
self.name = name
def get_gender(self, gender):
return ('{} is a {}').format(self.name, gender)
if __name__ == '__main__':
alex = Test('Alex')
anna = Test('Anna')
# 下面兩種方式都可以正確調用
print(alex.get_gender('boy'))
print(Test.get_gender(anna,'girl'))
運行結果爲:
Alex is a boy
Anna is a girl
【To be continue…】