原文是stackoverflow
的一則高票回答,原文連接
可能以前也有人翻譯過,可是恰好本身也有疑惑,因此搬運一下,我的水平有限因此可能翻譯存在偏差,歡迎指正(如侵刪)。python
儘管classmethod
和staticmethod
很是的類似,可是二者在具體的使用上仍是有着細微的差異:classmethod
必須使用類對象做爲第一個參數,而staticmethod
則能夠不傳遞任何參數。函數
讓咱們經過實際的例子來看看。spa
讓咱們假設有處理日期信息的類:翻譯
class Date(object): day = 0 month = 0 year = 0 def __init__(self, day=0, month=0, year=0): self.day = day self.month = month self.year = year
這個類很顯然能夠被用來存儲某些日期信息(不考慮時區信息;讓咱們假設全部的日期都用UTC
表示)code
這裏定義了__init__
,典型的類實例初始化方法,它做爲典型的instancemethod
接受參數,其中第一個傳遞的必要參數是新建的實例自己。對象
有一些能夠經過使用classmethod
很好解決的任務。繼承
假設咱們有不少('dd-mm-yyyy')
格式字符串的日期信息,想要把它們建立成Date
類實例。咱們不得不在項目的不一樣地方作這些事情。字符串
因此咱們必需要作到:get
- 分析獲得的年月日字符串,把它們轉化成三個整形變量或者擁有三個元素的元組的變量。
- 經過傳遞這些值實例化
Date
。
獲得:string
day, month, year = map(int, string_date.split('-')) date1 = Date(day, month, year)
C++擁有重載的特性能夠達到這種目的,可是Python缺少此類特性。因此,python使用classmethod
的方式。讓咱們嘗試一種另類的構造函數。
@classmethod def from_string(cls, date_as_string): day, month, year = map(date_as_string.split('-')) date1 = cls(day, month, year) return date1 date2 = Date.from_string('11-09-2012')
進一步分析一下以上代碼的執行,以及它的優點:
1.在一個地方解析日期字符串而且重複使用它。
2.作到很好的封裝(相對於把執行字符串解析做爲一個單獨的函數在任何地方執行,這裏使用的方法更符合OOP
的範式)
3.cls
表示類對象,而不是類實例。這樣很酷,由於若是咱們繼承Date
類,那麼全部的子類也都將擁有from_string
這個方法。
那麼staticmethod
又是什麼呢?它和classmethod
很是的類似,可是不強制要求傳遞參數(可是作的事與類方法或實例方法同樣)。
讓咱們來看一個使用的例子。
咱們有一個日期字符串須要以某種方式驗證。這個任務與以前同樣要定義在Date
類內部,可是不要求實例化它。
靜態方法在這種狀況下就很是有用。看一下下面這個代碼片斷:
@staticmethod def is_date_valid(date_as_string): day, month, year = map(int, date_as_string_split('-')) return day <= 31 and month <= 12 and year <= 3999 is_date = Date.is_date_valid('11-09-2012')
如今正如咱們瞭解到的staticmethod
的使用,咱們不須要訪問它所屬的類,它本質上就是一個函數,調用方式和調用函數同樣,不一樣的是它不關注對象和對象內部屬性。