在初學Python過程中,會遇到這樣的概念,一個類下面會有多個方法,有的叫類方法、有的叫靜態(tài)方法,還有的叫實例方法。當調用他們的時候,不免會有點蒙圈,那么他們之間的區(qū)別是什么呢?加我VX:atstudy-js 回復“測試”,進入 自動化測試學習交流群~~
![]()
和類屬性一樣,類方法可以進行細致地劃分為類方法、實例方法和靜態(tài)方法。
表象區(qū)別就是:
類方法前用@classmethod修飾
靜態(tài)方法前用@staticmethod修飾
不加任何修飾的就是實例方法(普通方法)
用法區(qū)別
實例方法
也是普通方法,實例方法是我們最常用的方法,它定義時最少要包含一個self參數,用于綁定調用此方法的實例對象(所謂綁定,即用實例調用的時候,不需要顯式的傳入)。
換句話說,當實例調用方法的時候,會默認將實例本身傳入到這個參數self,而當類直接調用時,因為本身類型是一個class,不是實例對象,所以報錯。
如果非要用類直接調用,需要手動傳入一個實例作為第一個參數。注意:若隨便傳入一個字符串的話,也不會報錯,但是會造成程序紊亂,因此不推薦這種調用方式。
用如下這段代碼舉例說明:
class A(object):
def instance_method(self, X):
print(f'instance_method :{X} : {self}')
a = A()
A.instance_method('x')
A.instance_method(a, 'x')
A.instance_method('strs', 'x')
a.instance_method('a')
代碼中 instance_method 為實例方法,而第6行類A調用了此方法,而實例方法默認傳入的應該是實例,而不是類,因此將x當做實例傳給了默認的self,此時實例方法還缺少一個參數沒有傳入,導致報錯:TypeError: instance_method() missing 1 required positional argument: 'x'。
第7行糾正了第6行的做法,傳入了實例a,且傳入了一個參數x,所以不會報錯,self就是A的實例a。
第8行將字符串代替實際的實例a傳入self,雖不會報錯,但是對于程序毫無價值,不推薦這樣使用,沒有意義。
第9行是最常用的方法,實例a調用了實例方法,默認將實例a傳入了self,再將參數x傳入了X,完整實現(xiàn)了調用。
本地方法
就當做實例方法的一種吧,好奇心的驅使,如果實例方法沒有添加self這個參數呢,為了區(qū)分,我們且叫他“本地方法”。所謂本地,也就是實例無法調用,只能類自己調用。
class A(object):
def local_method():
print(f'local_method')
def local_method2(strs):
print(f'local_method2')
a = A()
a.local_method()
a.local_method2()
A.local_method()
如上代碼,第2行的local_method()就是個本地方法,而此時在第9行實例a調用這個本地方法的時候,由于程序會默認將實例a傳入參數self,但是本地方法沒有寫self,因此報錯:TypeError: A.local_method() takes 0 positional arguments but 1 was given。
再看第5行的實例方法,為什么叫實例方法,明明沒有self啊?這里要特別說明下,self只是約定俗成的寫法,實際上隨便寫個什么字符串都可以的。因此第10行實例a調用實例方法,不會報錯,程序正常執(zhí)行。
第11行類A調用本地方法,也是不會報錯的。但如果類A調用實例方法就和第一節(jié)講的報錯了。
類方法
類方法有一個特點,就是這個方法必須要有@classmethod來修飾。和實例方法類似,至少也要傳一個參數,約定俗稱為cls,Python會自動將類本身綁定到這個參數上面。
類方法通常使用類直接調用,也可以用實例調用(不推薦)。當實例調用的時候,Python會將實例的最底層類(即實例直接所屬類)型傳入cls參數中。
class A(object):
name = 'I am Class A'
@classmethod
def class_method(cls, s):
print(cls.name) # 可以訪問類成員print(cls.name) # 可以訪問類成員
print(f"class_method : {cls} :: {s}")
class B(A):
name = 'I am Class B'
a = A()
b = B()
A.class_method('I am class')
a.class_method('I am instance')
B.class_method('I am B class')
b.class_method('I am b instance')
如上代碼,B類繼承了A類,并復寫了name屬性,而此時A類中的方法就是類方法,有兩個參數,一個是默認的類參數cls,還有一個普通入參。
第14行,A類直接調用自己的類方法,默認將自己傳入了cls,并將括號中的字符串傳給了參數s,用得恰到好處。此時第6行打印“I am Class A”可以看出,cls確實是傳的A。
第15行用A的實例a調用類方法,會默認將a的直屬類(也就是A)傳到cls中,因此效果和A調用是一樣的。
第16行用繼承類B調用的父類的類方法,既然是繼承,那么程序傳入的就是類B到cls中,由于B類中對name做了復寫,因此第6行打印出來的就是“I am Class B”。
第17行用繼承類B的實例b調用的父類的類方法,按照上述規(guī)則,是傳入的b的直屬類到cls中,也就是將B傳入了cls中,而不是A(這邊要注意區(qū)別),因此和B調用是一樣的。
靜態(tài)方法
靜態(tài)方法是使用@staticmethod修飾的方法,它不能訪問任何類屬性和類方法,因為它不含self或cls這些特殊參數,因此也無法訪問類或實例中的成員。
也就是說,Python沒有給他綁定實例或者類,要想使用,只能當參數來傳,所以在靜態(tài)方法中的入參都是普通參數,嚴格來講,上面說的本地方法應該也要寫成靜態(tài)方法。
class A(object):
@staticmethod
def static_method(a, b):
print(f"static_method : {a} + {b}")
a = A()
A.static_method('aa', 'bb')
a.static_method('aa', 'bb')
如上代碼中,盡管第7行類A調用了方法,但是由于是靜態(tài)方法,訪問不了類屬性,因此不會將類A傳入所謂的cls中,靜態(tài)方法中也沒有cls這個參數,因此它的參數都是普通入參。
第8行的實例調用也是和A一樣的效果。
所以邏輯上講,類方法應當只被類調用,實例方法只被實例調用,靜態(tài)方法兩者都能調用,主要區(qū)別在于參數傳遞上的區(qū)別。
實例方法悄悄傳遞的是self引用作為參數,而類方法悄悄傳遞的是cls引用作為參數。
要記住幾點
1.實例調用實例方法和本地方法時,Python默認將實例本身作為第一個參數傳入。
2.實例調用類方法時,Python默認將實例的最底層類作為第一個參數傳入。
3.實例調用靜態(tài)方法時,Python啥也不傳,需要幾個參數就要傳幾個參數。
4.類調用類方法時,Python默認將類本身作為第一個參數傳入。
5.類調用非類方法時,Python啥也不傳,需要幾個參數就要傳幾個參數。
最后:在我的V :atstudy-js,可以免費領取一份10G軟件測試工程師面試寶典文檔資料。以及相對應的視頻學習教程免費分享!其中包括了有基礎知識、Linux必備、Shell、互聯(lián)網程序原理、Mysql數據庫、抓包工具專題、接口測試工具、測試進階-Python編程、Web自動化測試、APP自動化測試、接口自動化測試、測試高級持續(xù)集成、測試架構開發(fā)測試框架、性能測試、安全測試等。
![]()
特別聲明:以上內容(如有圖片或視頻亦包括在內)為自媒體平臺“網易號”用戶上傳并發(fā)布,本平臺僅提供信息存儲服務。
Notice: The content above (including the pictures and videos if any) is uploaded and posted by a user of NetEase Hao, which is a social media platform and only provides information storage services.