日韩无码专区无码一级三级片|91人人爱网站中日韩无码电影|厨房大战丰满熟妇|AV高清无码在线免费观看|另类AV日韩少妇熟女|中文日本大黄一级黄色片|色情在线视频免费|亚洲成人特黄a片|黄片wwwav色图欧美|欧亚乱色一区二区三区

RELATEED CONSULTING
相關(guān)咨詢(xún)
選擇下列產(chǎn)品馬上在線(xiàn)溝通
服務(wù)時(shí)間:8:30-17:00
你可能遇到了下面的問(wèn)題
關(guān)閉右側(cè)工具欄

新聞中心

這里有您想知道的互聯(lián)網(wǎng)營(yíng)銷(xiāo)解決方案
就憑這3點(diǎn),可以完全理解Python的類(lèi)方法與靜態(tài)方法

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

創(chuàng)新互聯(lián)-專(zhuān)業(yè)網(wǎng)站定制、快速模板網(wǎng)站建設(shè)、高性?xún)r(jià)比柳江網(wǎng)站開(kāi)發(fā)、企業(yè)建站全套包干低至880元,成熟完善的模板庫(kù),直接使用。一站式柳江網(wǎng)站制作公司更省心,省錢(qián),快速模板網(wǎng)站建設(shè)找我們,業(yè)務(wù)覆蓋柳江地區(qū)。費(fèi)用合理售后完善,十余年實(shí)體公司更值得信賴(lài)。

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

可能很多同學(xué)不清楚這3種方法,尤其是后兩類(lèi)方法到底有什么不同。為此,本文將對(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 

類(lèi)方法必須使用@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ù)不同

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

self和cls分別表示類(lèi)實(shí)例和類(lèi)本身,這一點(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.     # 類(lèi)方法 
  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ò)類(lèi)實(shí)例調(diào)用,代碼如下:

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

在定義成員方法時(shí),第一個(gè)參數(shù)是表示類(lèi)實(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)用類(lèi)方法

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

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

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

 
 
 
 
  1. executing class_foo(, 20) 
  2. executing class_foo(, 20) 

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

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

調(diào)用靜態(tài)方法與調(diào)用類(lèi)方法一樣,都可以通過(guò)類(lèi)實(shí)例或類(lèi)本身調(diào)用,從這一點(diǎn)看不出來(lái)哪一個(gè)是類(lèi)方法,哪一個(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)有與類(lèi)或類(lèi)實(shí)例綁定,當(dāng)然,在靜態(tài)方法中,仍然可以通過(guò)MyClass引用類(lèi)中的靜態(tài)成員。

3. 方法歸屬

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

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

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

 
 
 
 
  1.  

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

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

4. 總結(jié)

(1)共同點(diǎn)

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

(2)差異

類(lèi)方法顧名思義,是與類(lèi)綁定的,相當(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) 

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

而靜態(tài)方法其實(shí)就是一個(gè)寄居蟹,完全不屬于它的宿主。只是寄居在類(lèi)中。換句話(huà)說(shuō),直接將靜態(tài)方法從類(lèi)中移出來(lái)作為獨(dú)立的函數(shù),完全不需要修改一行代碼就可以直接運(yùn)行。因?yàn)殪o態(tài)方法不會(huì)訪問(wèn)類(lèi)中的任何成員,當(dāng)然,可能訪問(wèn)類(lèi)的靜態(tài)成員,但也是使用類(lè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類(lèi)提供了靜態(tài)方法,可以通過(guò)MyClass.process(...)的形式在其他類(lèi)訪問(wèn)MyClass中的process方法。

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

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

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

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

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


分享名稱(chēng):就憑這3點(diǎn),可以完全理解Python的類(lèi)方法與靜態(tài)方法
本文URL:http://www.5511xx.com/article/coepdpg.html