初學Python過程中,例項方法和類方法的區別是什麼?

博為峰網校 發表於 2022-11-15
Python

在初學Python過程中,會遇到這樣的概念,一個類下面會有多個方法,有的叫類方法、有的叫靜態方法,還有的叫例項方法。當呼叫他們的時候,不免會有點蒙圈,那麼他們之間的區別是什麼呢? 加我VX:atstudy-js 回覆“測試”,進入 自動化測試學習交流群~~

初學Python過程中,例項方法和類方法的區別是什麼?

和類屬性一樣,類方法可以進行細緻地劃分為類方法、例項方法和靜態方法。

表象區別就是:

類方法前用@classmethod修飾

靜態方法前用@staticmethod修飾

不加任何修飾的就是例項方法(普通方法)

用法區別

例項方法

也是普通方法,例項方法是我們最常用的方法,它定義時最少要包含一個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,完整實現了呼叫。

本地方法

就當做例項方法的一種吧,好奇心的驅使,如果例項方法沒有新增self這個引數呢,為了區分,我們且叫他“本地方法”。所謂本地,也就是例項無法呼叫,只能類自己呼叫。

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呼叫例項方法,不會報錯,程式正常執行。

第11行類A呼叫本地方法,也是不會報錯的。但如果類A呼叫例項方法就和第一節講的報錯了。

類方法

類方法有一個特點,就是這個方法必須要有@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呼叫的父類的類方法,按照上述規則,是傳入的b的直屬類到cls中,也就是將B傳入了cls中,而不是A(這邊要注意區別),因此和B呼叫是一樣的。

靜態方法

靜態方法是使用@staticmethod修飾的方法,它不能訪問任何類屬性和類方法,因為它不含self或cls這些特殊引數,因此也無法訪問類或例項中的成員。

也就是說,Python沒有給他繫結例項或者類,要想使用,只能當引數來傳,所以在靜態方法中的入參都是普通引數,嚴格來講,上面說的本地方法應該也要寫成靜態方法。

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呼叫了方法,但是由於是靜態方法,訪問不了類屬性,因此不會將類A傳入所謂的cls中,靜態方法中也沒有cls這個引數,因此它的引數都是普通入參。

第8行的例項呼叫也是和A一樣的效果。

所以邏輯上講,類方法應當只被類呼叫,例項方法只被例項呼叫,靜態方法兩者都能呼叫,主要區別在於引數傳遞上的區別。

例項方法悄悄傳遞的是self引用作為引數,而類方法悄悄傳遞的是cls引用作為引數。

要記住幾點

1.例項呼叫例項方法和本地方法時,Python預設將例項本身作為第一個引數傳入。

2.例項呼叫類方法時,Python預設將例項的最底層類作為第一個引數傳入。

3.例項呼叫靜態方法時,Python啥也不傳,需要幾個引數就要傳幾個引數。

4.類呼叫類方法時,Python預設將類本身作為第一個引數傳入。

5.類呼叫非類方法時,Python啥也不傳,需要幾個引數就要傳幾個引數。

最後:

可以到我的個人V:atstudy-js,可以免費領取一份10G軟體測試工程師面試寶典文件資料。以及相對應的影片學習教程免費分享!其中包括了有基礎知識、Linux必備、Mysql資料庫、抓包工具、介面測試工具、測試進階-Python程式設計、Web自動化測試、APP自動化測試、介面自動化測試、測試高階持續整合、測試架構開發測試框架、效能測試等。

這些測試資料,對於做【軟體測試】的朋友來說應該是最全面最完整的備戰倉庫,這個倉庫也陪伴我走過了最艱難的路程,希望也能幫助到你!

來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/31407649/viewspace-2923502/,如需轉載,請註明出處,否則將追究法律責任。