昨天同事問我一個關於Python靜態方法和類方法的區別,上網找了些資料整理一下:
@staticmethod和@classmethod都是用來定義靜態函數的,它們的相同點是都不用實例化類,能夠直接用類名來調用其相關屬性。不一樣點是,@classmethod的第一個參數是cls,所以能夠訪問類變量。@staticmethod只是自身代碼在類裏面,對類的其它再無相關。通常狀況下用@classmethod,@staticmethod只適用於不想定義全局函數的狀況。
下面是摘抄自Python核心編程第二版:
靜態方法和類方法
靜態方法和類方法在 Python2.2 中引入。經典類及新式(new-style)類中均可以使用它。一對內
建函數被引入,用於將做爲類定義的一部分的某一方法聲明「標記」(tag),「強制類型轉換」(cast)
或者「轉換」(convert)爲這兩種類型的方法之一。
若是你有必定的C++或者Java經驗,靜態方法和這些語言中的是同樣的。它們僅是類中的函數(不
須要實例)。事實上,在靜態方法加入到 Python 以前,用戶只能在全局名字空間中建立函數,做爲
這種特性的替代實現 - 有時在這樣的函數中使用類對象來操做類(或者是類屬性)。使用模塊函數
比使用靜態類方法更加常見。
回憶一下,一般的方法須要一個實例(self)做爲第一個參數,而且對於(綁定的)方法調用來
說,self 是自動傳遞給這個方法的。而對於類方法而言,須要類而不是實例做爲第一個參數,它是
由解釋器傳給方法。類不須要特別地命名, 相似 self,不過不少人使用 cls 做爲變量名字。
staticmethod()和 classmethod()內建函數
如今讓咱們看一下在經典類中建立靜態方法和類方法的一些例子(你也能夠把它們用在新式類
中):
class TestStaticMethod:
def foo():
print 'calling static method foo()'
foo = staticmethod(foo)
class TestClassMethod:
def foo(cls):
print 'calling class method foo()'
print 'foo() is part of class:', cls.__name__
foo = classmethod(foo)
對應的內建函數被轉換成它們相應的類型,而且從新賦值給了相同的變量名。若是沒有調用這
兩個函數,兩者都會在 Python 編譯器中產生錯誤,顯示須要帶 self 的常規方法聲明。如今, 咱們
能夠經過類或者實例調用這些函數....這沒什麼不一樣:
>>> tsm = TestStaticMethod()
>>> TestStaticMethod.foo()
calling static method foo()
>>> tsm.foo()
calling static method foo()
>>>
>>> tcm = TestClassMethod()
>>> TestClassMethod.foo()
calling class method foo()
foo() is part of class: TestClassMethod
>>> tcm.foo()
Edit By Vheavens
Edit By Vheavens
calling class method foo()
foo() is part of class: TestClassMethod
使用函數修飾符
如今,看到像 foo=staticmethod(foo)這樣的代碼會刺激一些程序員。不少人對這樣一個沒意義
的語法感到心煩,即便 van Rossum 曾指出過,它只是臨時的,有待社區對些語義進行處理。在第 11
章「函數」的 11.3.6 節中,咱們瞭解了函數修飾符,一種在 Python2.4 中加入的新特徵。你能夠用
它把一個函數應用到另個函數對象上, 並且新函數對象依然綁定在原來的變量。咱們正是須要它來
整理語法。經過使用 decorators,咱們能夠避免像上面那樣的從新賦值:
class TestStaticMethod:
@staticmethod
def foo():
print 'calling static method foo()'
class TestClassMethod:
@classmethod
def foo(cls):
print 'calling class method foo()'
print 'foo() is part of class:', cls.__na