python的@classmethod和@staticmethod

來源:互聯網
上載者:User

標籤:tps   params   函數   param   date   情況下   物件導向   法則   ima   

本文是對StackOverflow上的一篇高贊回答的不完全翻譯,原文連結:meaning-of-classmethod-and-staticmethod-for-beginner

Python物件導向編程中,類中定義的方法可以是@classmethod 裝飾的類方法,也可以是@staticmethod 裝飾的靜態方法,用的最多的還是不帶裝飾器的執行個體方法。為方便,在下文中用@classmethod裝飾的類方法將直接用@classmethod來表述,@staticmethod同理,望讀者在閱讀時自行加以區分。

@classmethod和@staticmethod很相似,它們裝飾的方法在使用上只有一點區別:@classmethod裝飾的方法第一個參數必須是一個類(通常為cls),而@staticmethod裝飾的方法則按業務需求設定參數,也可以根本沒有參數。

 

範例

範例是一個處理日期資訊的類,如下:

  1. class Date(object):
  2.  
  3. def __init__(self, day=0, month=0, year=0):
  4. self.day = day
  5. self.month = month
  6. self.year = year

這個類可以用來儲存指定日期(不包括時區資訊,假設所有日期都是UTC時間)。

        這個類有一個__init__函數用來初始化執行個體對象,它的第一個必須的參數self指向一個已建立的Date類的執行個體對象,這個方法是一個典型的執行個體方法。

 

Class Method

 

有些任務用@classmethod 可以很好地完成。

假設我們要從一堆有著特定日期格式的字串(如‘dd-mm-yyyy‘)建立很多對應的Date類的執行個體,而且在項目的各個地方都要進行這樣的轉換。那麼我們要做的是:

1. 解析一個字串來得到day,month,year這三個整數變數或者組裝出一個tuple

2. 把這些值傳遞給初始化函數來執行個體化Date執行個體對象

比如:

  1. day, month, year = map(int, string_date.split(‘-‘))
  2. date1 = Date(day, month, year)

 

要實現這個目的,C++可以使用重載,但是Python沒有這樣的文法,但是可以使用@classmethod來實現,如下:

  1. @classmethod
  2. def from_string(cls, date_as_string):
  3. day, month, year = map(int, date_as_string.split(‘-‘))
  4. date1 = cls(day, month, year)
  5. return date1
  6.  
  7. date2 = Date.from_string(‘11-09-2012‘)

仔細比較這兩種方法,使用@classmethod有以下優點:

1. 我們唯寫了一個轉換字串的方法,而且這個方法是可重用的。

2. 把這個方法封裝在類中,更緊密(也許你會認為可以寫一個單獨的函數去轉換字串,但是使用@classmethod更符合物件導向的思維)。

3. cls 是類本身的對象,而不是類的執行個體對象,這樣的話繼承自Date的對象都會有from_string這個方法。

 

Static Method

那麼@staticmethod呢?其實它跟@classmethod非常相似,只是它沒有任何必要參數。

假設我們要去檢驗一個日期的字串是否有效。這個任務與Date類相關,但是又不需要Date執行個體對象,在這樣的情況下@staticmethod就可以派上用場了。如下:

  1. @staticmethod
  2. def is_date_valid(date_as_string):
  3. day, month, year = map(int, date_as_string.split(‘-‘))
  4. return day <= 31 and month <= 12 and year <= 3999
  5.  
  6. # usage:
  7. is_date = Date.is_date_valid(‘11-09-2012‘)

從上面的用法可以看出,它只是一個功能,調用的文法和一般的方法調用一樣,也不訪問執行個體對象那和它的內部欄位和方法。

 

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

以下有錯誤的地方

 

類的普通方法

class Animal(object):    def __init__(self,name):        self.name = name    def intro(self):        print(‘there is a %s‘%(self.name))cat = Animal(‘cat‘)cat.intro()
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

靜態類方法

class Animal(object):    def __init__(self,name):        self.name = name    @staticmethod    def intro(self):        print(‘there is a %s‘%(self.name))cat = Animal(‘cat‘)cat.intro()
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

加上裝飾器後運行會報錯,原因是方法變為一個普通函數,脫離的與類的關係,不能引用建構函式中的變數了。

使用情境舉例:python內建方法os中的方法,可以直接使用的工具包,跟類沒關係。

class Animal(object):    def __init__(self,name):        self.name = name    @classmethod    def intro(self):        print(‘there is a %s‘%(self.name))cat = Animal(‘cat‘)cat.intro()
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

報錯資訊

如果換成

class Animal(object):    name = ‘cat‘    def __init__(self,name):        self.name = name    @classmethod    def intro(self):        print(‘there is a %s‘%(self.name))cat = Animal(‘cat‘)cat.intro()
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9

可以正常運行。
結論:類方法只能調用類變數,不能調用執行個體變數

屬性方法@property 把一個方法變為(偽裝成)類屬性。因為類屬性的實質是一個類變數,使用者可以調用變數就可以修改變數。某些特定情境要限制使用者行為,就用到靜態方法。
@property廣泛應用在類的定義中,可以讓調用者寫出簡短的代碼,同時保證對參數進行必要的檢查,這樣,程式運行時就減少了出錯的可能性。(摘自廖雪峰的部落格)

class Animal(object):    def __init__(self,name):        self.name = name    @property    def intro(self,food):        print(‘there is a %s eating %s‘%(self.name,food))cat = Animal(‘cat‘)cat.intro()
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

報錯:
方法不能正常調用。如果要調用,如下:

cat.intro
  • 1

但是這樣的話,方法就沒辦法單獨傳入參數。如果要傳入參數,如下:

class Animal(object):    def __init__(self,name):        self.name = name    @property    def intro(self):        print(‘there is a %s eating %s‘%(self.name,food))    @intro.setter    def intro(self,food):        passcat = Animal(‘cat‘)cat.intro
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11

cat.intro還有其他動作getter deleter等等。

 

python的@classmethod和@staticmethod

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.