自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

就憑這3點(diǎn),可以完全理解Python的類方法與靜態(tài)方法

開(kāi)發(fā) 后端
如果只是描述類的一般的動(dòng)作,而且類的不同實(shí)例,動(dòng)作的表現(xiàn)可能還不同,那么就用成員方法,例如,move(移動(dòng))、fly(飛)、getAge(如不同Person類的實(shí)例,可能年齡是不同的)等。

[[386004]]

在Python語(yǔ)言中有如下3種方法:

  • 成員方法
  • 類方法(classmethod)
  • 靜態(tài)方法(staticmethod)

可能很多同學(xué)不清楚這3種方法,尤其是后兩類方法到底有什么不同。為此,本文將對(duì)這3種方法做一次敲骨瀝髓的深度剖析。

先說(shuō)一下這3種方法的差異,了解差異后,就自然了解他們的區(qū)別了。

這3種方法有如下3點(diǎn)差異:

  • 方法定義
  • 調(diào)用方式
  • 方法歸屬

1. 方法定義

這3種方法在定義上有如下2點(diǎn)不同。

(1)是否使用裝飾器

成員方法不需要使用任何裝飾器,直接使用def關(guān)鍵字定義方法即可,代碼如下:

  1. def method(self, a, b, c): 
  2.     pass 

類方法必須使用@classmethod裝飾器修飾,代碼如下:

  1. @classmethod 
  2. def method(cls, a, b, c): 
  3.     pass 

靜態(tài)方法必須使用@staticmethod裝飾器修飾,代碼如下:

  1. @staticmethod 
  2. def method(a, b, c): 
  3.     pass 

(2)參數(shù)不同

成員方法與類方法,除正常的方法參數(shù)外,都必須多加一個(gè)參數(shù),這個(gè)參數(shù)必須是方法的第1個(gè)參數(shù)。參數(shù)可以是任意名,但通常成員方法的第1個(gè)參數(shù)名是self,類方法的第1個(gè)參數(shù)名是cls。而靜態(tài)方法不需要加額外的參數(shù)。見(jiàn)前面代碼中的method方法。

self和cls分別表示類實(shí)例和類本身,這一點(diǎn)在后面會(huì)詳細(xì)介紹。

下面看一個(gè)完整定義這3種方法的代碼:

  1. class MyClass(object): 
  2.     # 成員方法    
  3.     def foo(self, x): 
  4.         print("executing foo(%s, %s)" % (self, x)) 
  5.     # 類方法 
  6.     @classmethod 
  7.     def class_foo(cls, x): 
  8.         print("executing class_foo(%s, %s)" % (cls, x)) 
  9.     # 靜態(tài)方法  
  10.     @staticmethod 
  11.     def static_foo(x): 
  12.         print("executing static_foo(%s)" % x) 

2. 調(diào)用方式

(1)調(diào)用成員方法

成員方法只能通過(guò)類實(shí)例調(diào)用,代碼如下:

  1. my = MyClass() 
  2.  
  3. my.foo(20) 

在定義成員方法時(shí),第一個(gè)參數(shù)是表示類實(shí)例的self,這個(gè)參數(shù)并不需要在調(diào)用時(shí)顯式指定,而是由Python運(yùn)行時(shí)自動(dòng)處理。對(duì)于上面的調(diào)用代碼,Python運(yùn)行時(shí)會(huì)自動(dòng)將表示MyClass實(shí)例的my傳入foo方法。所以my就是foo方法中第一個(gè)參數(shù)self的值。通過(guò)self,在方法內(nèi)部可以引用MyClass實(shí)例的其他成員。

執(zhí)行這段代碼,會(huì)輸出如下內(nèi)容。很明顯,self是一個(gè)對(duì)象,首地址是0x7f7f1003df70

  1. executing foo(<__main__.MyClass object at 0x7f7f1003df70>, 20) 

(2)調(diào)用類方法

類方法可以通過(guò)類實(shí)例調(diào)用,也可以直接通過(guò)類本身調(diào)用,代碼如下:

  1. my = MyClass() 
  2. # 通過(guò)類實(shí)例調(diào)用 
  3. my.class_foo(20) 
  4. # 通過(guò)類本身調(diào)用 
  5. MyClass.class_foo(20) 

執(zhí)行這段代碼,會(huì)輸出如下內(nèi)容:

  1. executing class_foo(<class '__main__.MyClass'>, 20) 
  2. executing class_foo(<class '__main__.MyClass'>, 20) 

很明顯,class_foo方法的cls參數(shù)不再是類的實(shí)例(因?yàn)闆](méi)有對(duì)象地址),而是MyClass類本身。所以不管使用哪一種方式調(diào)用類方法,傳入class_foo方法第1個(gè)參數(shù)的值都是類本身。所以通過(guò)類方法,可以獲取類的靜態(tài)資源,與直接引用MyClass是一樣的。

(3)調(diào)用靜態(tài)方法

調(diào)用靜態(tài)方法與調(diào)用類方法一樣,都可以通過(guò)類實(shí)例或類本身調(diào)用,從這一點(diǎn)看不出來(lái)哪一個(gè)是類方法,哪一個(gè)是靜態(tài)方法,代碼如下:

  1. my = MyClass() 
  2. MyClass.static_foo(20) 
  3. my.static_foo('hello'

執(zhí)行這段代碼,會(huì)輸出如下內(nèi)容:

  1. executing static_foo(20) 
  2. executing static_foo(hello) 

由于在定義靜態(tài)方法時(shí)并沒(méi)有指定任何額外的參數(shù),所以靜態(tài)方法并沒(méi)有與類或類實(shí)例綁定,當(dāng)然,在靜態(tài)方法中,仍然可以通過(guò)MyClass引用類中的靜態(tài)成員。

3. 方法歸屬

方法歸屬是這3種方法的重要區(qū)別,可以分別將這3種方法作為屬性輸出,看看是什么結(jié)果。

  1. my = MyClass()) 
  2. # 輸出成員方法 
  3. print(my.foo) 
  4. # 輸出類方法 
  5. print(my.class_foo) 
  6. # 輸出靜態(tài)方法 
  7. print(my.static_foo) 

執(zhí)行這段代碼,會(huì)輸出如下內(nèi)容:

  1. <bound method MyClass.foo of <__main__.MyClass object at 0x7f7f1003df70>> 
  2. <bound method MyClass.class_foo of <class '__main__.MyClass'>> 
  3. <function MyClass.static_foo at 0x7f7f1003ad30> 

從輸出結(jié)果可以看到,成員方法綁定到了類實(shí)例中(該方法屬于類實(shí)例),類方法與類本身綁定,而靜態(tài)方法就是一個(gè)獨(dú)立的對(duì)象(因?yàn)橛袑?duì)象首地址),不屬于任何類或?qū)嵗?/p>

從以上3個(gè)方法我們已經(jīng)可以得出classmethod方法與staticmethod的區(qū)別,下面總結(jié)一下:

4. 總結(jié)

(1)共同點(diǎn)

classmethod方法與staticmethod方法的共同點(diǎn)只有一個(gè),就是調(diào)用時(shí),既可以使用類實(shí)例,也可以直接用類本身調(diào)用。所以從調(diào)用上,根本分不出是類方法,還是靜態(tài)方法。

(2)差異

類方法顧名思義,是與類綁定的,相當(dāng)于下面的調(diào)用方式:

  1. def process(cls, x): 
  2.     print(cls,x) 
  3. MyClass.process = process 
  4. # 調(diào)用process方法時(shí)直接傳入了MyClass 
  5. MyClass.process(MyClass, 20) 

只是類方法在調(diào)用時(shí)自動(dòng)傳入了MyClass,而上面的代碼是顯式傳入MyClass的,但最終效果是完全一樣的。

而靜態(tài)方法其實(shí)就是一個(gè)寄居蟹,完全不屬于它的宿主。只是寄居在類中。換句話說(shuō),直接將靜態(tài)方法從類中移出來(lái)作為獨(dú)立的函數(shù),完全不需要修改一行代碼就可以直接運(yùn)行。因?yàn)殪o態(tài)方法不會(huì)訪問(wèn)類中的任何成員,當(dāng)然,可能訪問(wèn)類的靜態(tài)成員,但也是使用類本身(如MyClass),這種訪問(wèn)方式,獨(dú)立的函數(shù)同樣可以。

其實(shí)Python提供靜態(tài)方法倒不是非常必要,不過(guò)Java就很有必要了。由于Python支持獨(dú)立的函數(shù)形式,所以不使用靜態(tài)方法,也可以使用獨(dú)立的函數(shù)。通常獨(dú)立的函數(shù)可以全局訪問(wèn)(在一個(gè)模塊訪問(wèn)另外一個(gè)模塊中的函數(shù))。而Java是純面向?qū)ο笳Z(yǔ)言,并不支持獨(dú)立函數(shù)。所以為了實(shí)現(xiàn)這種全局調(diào)用的效果,Java類提供了靜態(tài)方法,可以通過(guò)MyClass.process(...)的形式在其他類訪問(wèn)MyClass中的process方法。

不過(guò)Python中的靜態(tài)方法到是有一個(gè)作用,就是分組。如果模塊中有大量的獨(dú)立函數(shù),而且這些獨(dú)立函數(shù)的功能可能完全不同,就顯得比較亂,所以通常的做法是將這些獨(dú)立函數(shù)作為Python類的靜態(tài)方法,將同一類型的獨(dú)立函數(shù)放到一個(gè)類中,這樣就會(huì)讓整個(gè)代碼結(jié)構(gòu)顯得更有調(diào)理。就像將文件存放在硬盤上一樣,如果將所有的文件都放在一個(gè)目錄中,找文件會(huì)很費(fèi)勁。所以需要將同一類文件放到特定的目錄中,這樣看起來(lái)目錄結(jié)構(gòu)更清晰。所以靜態(tài)方法與Python類,就相當(dāng)于文件與目錄的關(guān)系,主要就是起到分類的作用。

(3)使用場(chǎng)景

如果只是描述類的一般的動(dòng)作,而且類的不同實(shí)例,動(dòng)作的表現(xiàn)可能還不同,那么就用成員方法,例如,move(移動(dòng))、fly(飛)、getAge(如不同Person類的實(shí)例,可能年齡是不同的)等。

類方法與靜態(tài)方法大多數(shù)時(shí)候可以互換,但如果想讓方法保持獨(dú)立,應(yīng)該使用靜態(tài)方法,因?yàn)殪o態(tài)方法不需要多余的參數(shù)接收類或類實(shí)例。

本文轉(zhuǎn)載自微信公眾號(hào)「極客起源」,可以通過(guò)以下二維碼關(guān)注。轉(zhuǎn)載本文請(qǐng)聯(lián)系極客起源公眾號(hào)。

 

責(zé)任編輯:武曉燕 來(lái)源: 極客起源
相關(guān)推薦

2021-04-21 10:01:53

Python類方法靜態(tài)方法

2009-08-28 12:41:49

靜態(tài)方法與非靜態(tài)方法

2018-04-26 09:00:00

2022-08-13 13:00:43

SQL語(yǔ)言

2025-04-14 08:35:00

Python類裝飾器裝飾器

2019-08-20 14:40:35

Redis數(shù)據(jù)庫(kù)

2021-04-14 10:59:28

JavaScript 前端this

2018-11-15 10:04:02

機(jī)柜方法布線

2021-09-13 07:53:30

安全

2015-11-18 11:56:23

Linux

2015-09-18 11:14:54

2021-10-08 20:11:40

類方法靜態(tài)

2018-05-04 11:22:21

APP運(yùn)營(yíng)pushapp卸載

2010-11-09 16:14:52

卸載SQL Serve

2011-11-11 10:35:04

2010-08-17 14:47:49

FirefoxJavascript

2011-09-06 14:08:22

IIS

2018-09-12 15:16:19

數(shù)據(jù)中心網(wǎng)絡(luò)機(jī)房

2018-08-10 00:03:08

網(wǎng)速網(wǎng)絡(luò)連接Wi-Fi

2021-08-16 09:35:34

Collections Java開(kāi)發(fā)
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)