1. 程式人生 > 程式設計 >深入瞭解Python 方法之類方法 & 靜態方法

深入瞭解Python 方法之類方法 & 靜態方法

寫在之前

這幾天的閱讀量蜜汁低,是什麼原因我也沒搞清楚,如果你們覺得我哪裡寫的有問題,或者是哪裡不好,歡迎後臺或者微信告知我,先行謝過。

昨天的文章 詳解類方法之繫結方法與非繫結方法 中寫了方法中的繫結方法和非繫結方法,今天我們繼續來學習剩下的「類方法」和「靜態方法」。

類方法 & 靜態方法

在開始之前,先讓我們來看下面一段程式碼:

class Sample:
  language = "C++"
  def __init__(self):
    self.language = "python"

def get_class_attr(cls):
  return cls.language

if __name__ == "__main__":
  print("sample.language:",Sample.language)
  r = get_class_attr(Sample)
  print("get class attribute:",r)
  f = Sample()
  print("instance attribute:",f.language)

上述程式碼在類 Sample 中,定義了一個屬性 language = “C++”,這個是「類屬性」;在初始化方法中,又定義了 self.language = “python”,這個是「例項屬性」。

知道了這個,我們然後來分析一下函式 get_class_attr(cls),在這個函式中引數用的是 cls,從函式體來看,要求它引用的物件應該具有屬性 language,這說明,不是隨隨便便哪個物件都可以。很巧的是在前面定義的類 Sample 中就有 language 這個屬性,於是在呼叫這個函式的時候,就直接將該類物件作為方法 get_class_attr() 的引數。

Sample.language 是要得到類屬性的值,get_class_attr(Sample) 所返回的就是類 Sample 的屬性 Sample.language 的值,所以對於上述例子來說,前面兩個 print() 函式列印的結果應該是一樣的。

f = Sample() 則是建立了一個例項,然後通過 f.language 訪問例項屬性。所以對於上述的程式碼的執行結果如下所示:

sample.language:C++
get class attribute:C++
instance attribute:python

不知道經過我上述的解釋你是否明白了,如果沒明白,建議你再仔細對比一下上述的執行結果和分析的過程。

在上述的例子中,比較特殊的函式應該是 get_class_attr(cls),它是寫在類的外面的,然而這個函式又只能呼叫前面寫的那個類物件,因為不是所有物件都有那個特別的 language 屬性,這種函式寫在外面不利於後期的維護,我們應該避免這種情況的發生,而避免的方法就是把函式和類寫在一起,所以就有了下面這種寫法:

class sample:
  language = "C++"
  def __init__(self):
    self.language = "python"

  @classmethod
  def get_class_attr(cls):
    return cls.language

if __name__ == "__main__":
  print("sample.language:",sample.language)
  r = sample.get_class_attr()
  print("get class attribute:",r)
  f = sample()
  print("instance attribute:",f.language)
  print("instance get_class_str:",f.get_class_attr())

在上面這個修改的程式碼中,出現了 @classmethod,這是一個裝飾器,我們在函式的那部分講到過。這裡需要我們注意的是,@classmethod 所裝飾的方法的引數中,第一個引數不是 self,這個和我們常規認識中的類的方法有所區別。這裡使用了引數 cls,這是習慣的寫法,當然用其它的也可以。讓我們來看一下執行的結果:

sample.language:C++
get class attribute:C++
instance attribute:python
instance get_class_str:C++

通過上面的執行結果我們可以看到,不管是通過類還是例項來執行 get_class_attr() 得到的結果都是類屬性的值,這說明裝飾器 @classmethod 所裝飾的方法,它的引數 cls 引用的物件是類物件 Sample。

至此,「類方法」 的定義就出來了:類方法,就是在類裡面定義的方法。該方法由裝飾器 @classmethod 裝飾,其第一個引數 cls 引用的是這個類物件,即將類本身作為作為引用物件傳到這個方法裡。

知道了類方法以後,我們可以用同樣的思路理解另一個方法 「靜態方法」,我們還是先來看一段程式碼:

import random

def judge(n):
  num = random.randint(1,100)
  return num - n > 0

class Sample:
  def __init__(self,name):
    self.name = name

  def get_name(self,age):
    if judge(age):
      return self.name
    else:
      return "the name is stupid"

if __name__ == "__main__":
  s = Sample('rocky')
  name = s.get_name(23)
  print(name)

先看一下上面的程式碼,類 Sample 裡面使用了外面的函式 judge(n),這種類和函式的關係也是因為相互關聯,所以後期的程式維護可能會出問題,於是為了便於維護,我們同樣對程式進行了修改:

import random

class Sample:
  def __init__(self,age):
    if self.judge(age):
      return self.name
    else:
      return "the name is stupid"
  @staticmethod
  def judge(n):
    num = random.randint(1,100)
    return num - n > 0

if __name__ == "__main__":
  s = Sample('rocky')
  name = s.get_name(23)
  print(name)

同樣是經過修改優化,將原來在類外面的函式放到了類裡面。但是這不是簡單的移動,還要在函式的前面加上 @staticmethod 裝飾器,並且要注意的是,雖然這個函式在類的裡面,但是跟別的方法是不一樣的,它的第一個引數也不是 self,當我們要使用它的時候,可以通過例項呼叫,比如 self.judge(n),也可以通過類呼叫這個方法,比如 sample.select(n)。

從上面的程式可以看出,儘管 judge(n) 位於類裡面,但它確實一個獨立的方法,與類本身沒有關係,僅僅是為了免除前面所說的後期維護上的麻煩。但是它也有存在的道理,上面的例子就是一個典型的說明。

所以「靜態方法」的定義也就出來了:在類的作用域裡面,前面必須要加上一個 @staticmethod 裝飾器,我們將這種方法命名為靜態方法。

寫在之後

方法是類的重要組成部分,本章所講的類方法和靜態方法讓我們在使用類的時候有了更加便利的工具。

「方法」的這一塊到這裡就補充完了,之後我們將繼續學習 OOP 的剩下兩個特徵:「多型」和「封裝」,敬請期待。

如果你覺得本篇文章讓你有所收穫,歡迎點贊轉發,你的支援是對我碼字最大的動力,分享永遠在路上,我們一起加油。

The end。

以上就是深入瞭解Python 方法之類方法 & 靜態方法的詳細內容,更多關於python 類方法和靜態方法的資料請關注我們其它相關文章!