Python靜態方法,其實暗藏玄機


文章首發於 微信公眾號:Python編程時光

這個標題「靜態方法其實暗藏玄機」其實只是該文章的一個知識點。或許有些標題黨,但沒有關系,我相信有不少人對此並沒有深入研究他們,不信我問你三個問題,你看能否答上來。

1、Python2.x和3.x中,函數和方法的區分有什么不同?

2、有了類/實例方法和普通函數,為什么還會有靜態方法?

3、Python3.x 中,靜態方法有幾種寫法?

帶着這三個問題,你可以嘗試在下文中尋找答案。


在 Python 2 中的函數和方法的區別,十分清晰,很好分辨。但在 Python3中,我卻發現完全又是另一套准則。

首先先來 Python2 的(以下在 Python2.7中測試通過)

可以得出結論:

1、普通函數(未定位在類里),都是函數。

2、靜態方法(@staticmethod),都是函數。

3、類方法(@classmethod),都是方法。

4、實例方法(首參數為self且非靜態、非類方法的),都是方法。

你一定想說,類方法和實例方法,是方法沒錯呀,畢竟名字本身就有方法,普通函數是函數,我也理解呀。那靜態方法,為什么不是方法而是函數呢?

名字只是一個外在的表面稱呼,你能說「趙鐵男」就一定是漢子嗎?

我的理解是:方法是一種和對象(實例或者類)綁定后的函數。

類方法的首參是cls,調用時,無需顯示傳入。實例方法首參是self,調用時,也無需顯示傳入。

而靜態方法,其實和普通函數沒啥區別,唯一的區別就是,他定義的位置被放在了類里,做為類或者實例的一個函數。

那你肯定又要問了,既然靜態方法和普通函數都是一樣的,為什么要刻意將它放在類里呢?

我上面說了,放在類里定義,就可以讓它成為類的一個工具函數,這就像你身上隨身攜帶了一把刀,這把刀與你本人並沒有什么直接關系,唯一的聯系就是這把刀是你的,而你把它帶在身上,無論你去到哪里,只要需要,你就可以直接拿出來用上。對比將函數放在類外面,缺點是什么呢?就是當你出門在外(在別的模塊里)發現你要用刀的時候,還要特地跑一趟去商店買一把刀(import 這個函數)。

另外,我覺得靜態方法在業務和設計上的意義,會更多一些。

一般靜態方法是做為類或者實例的一個工具函數,比如對變量的做一個合法性的檢驗,對數據進行序列化反序列化操作等等。

說完了 Python2 ,再來說說Python3.

以前我覺得 Python2 對於方法和函數的界線更加清晰,但接觸了 Python3,我反而覺得Python3里方法和函數的區分似乎更加合理。

還是剛剛那段代碼,我更改了解釋器為Python3.6(以下在 Python3.6中測試通過)

和Python2的唯一區別是,People.jump 在Python3 中變成了函數。

這一下顛覆了你剛剛才建立起來的知識體系有木有?

先別急,我再做個試驗,也許你就知道了。

在 Python2中

執行People.jump('hello'),會報錯說,jump的首參必須為People的實例對象,這可以理解,畢竟jump定義時,第一個參數為self。

在 Python3中

你可以發現,這里的jump的首參不再要求是 People 的一個實例,而可以是任意的對象,比如我使用字符串對象,也沒有報錯。

也就是說,當你往jump中傳入的首參為People的實例時,jump 就是方法,而當你傳入的首參不是People的實例對象時,jump就是函數。

你看,多么靈活呀。

再總結一下,在Python3中:

1、普通函數(未定位在類里),都是函數。

2、靜態方法(@staticmethod),都是函數。

3、類方法(@classmethod),都是方法。

4、方法和函數區分沒有那么明確,而是更加靈活了,一個函數有可能是方法也有可能是函數。

你肯定又要問了,那這是不是就意味着,Python3 中靜態方法,可以不用再使用@staticmethod 裝飾了呢,反正Python3都可以識別。

這是個好問題,是的,可以不用指定,但是最好指定,如果你不指定,你調用這個方法只能通過People.jump,而不能通過 self.jump了,因為首參不是 self,而如果使用@staticmethod 就可以使用self.jump。

所以說這是一個規范,就像類的私有方法,規范要求外部最好不要調用,但這不是強制要求,不是說外部就不能調用。

寫這篇文章的起源,是前兩天有位讀者在交流里問到了相關的問題,正好沒什么主題可以寫,就拿過來做為素材整理一下,也正好沒有寫過靜態方法、類方法的內容,沒想到簡單的東西,也能寫出這么多的內容出來。

關注公眾號,獲取最新干貨!


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM