從self cls看Python的例項化 md

2021-08-30 22:09:46 字數 3946 閱讀 2661

剛開始學習python的時候經常會有乙個疑問,為什麼每個類方法的第乙個參與一定要加乙個self?經過一定的編碼後發現,怎麼還有一些類方法裡面寫的是cls

在使用類方法的時候,我們通常會把乙個類做例項化之後再進行呼叫,比如這樣:

class

calc

(object):

defadd

(self, x, y)

:print x + y

if __name__ ==

'__main__'

: calc = calc(

) calc.add(1,

1)

這個self到底是什麼呢?我們加兩行**來看。

class

calc

(object):

defadd

(self, x, y)

:print x + y

print self

if __name__ ==

'__main__'

: calc = calc(

) calc.add(1,

1)print calc -

-->

2<__main__.calc object at 0x108b4e4d0

>

<__main__.calc object at 0x108b4e4d0

>

可以看的出來,這個self和例項化出來的calc都是calc這個物件,並且指向的記憶體位址是同乙個,也就是他們兩個是同乙個東西。

在看別人的**的時候,經常會看到乙個@staticmethod。這個東西是靜態方法,在類中的方法都必須要傳self物件,但是一旦被@staticmethod裝飾器裝飾後的方法,就不需要傳入self這個引數,如下:

class

calc

(object):

defadd

(self, x, y)

:print x + y

@staticmethod

defminus

(x, y)

:print x - y

if __name__ ==

'__main__'

: calc = calc(

) calc.add(1,

1)calc.minus(3,

2)

具體來說這個有什麼用?我個人理解來說在python這個裝飾器只是乙個基於類設計的乙個方法。你用乙個def來實現,或者就用類方法來實現影響其實並不大。當然,你例項化了,也是可以通過例項來呼叫靜態方法的。

python中還有乙個方法@classmethod,使用了這個方法,傳入的第乙個引數就不是self,而是cls。比如這樣:

class

calc

(object):

defadd

(self, x, y)

:print x + y

@staticmethod

defminus

(x, y)

:print x - y

@classmethod

defmulti

(cls, x, y)

:print x * y

if __name__ ==

'__main__'

: calc = calc(

) calc.add(1,

1)calc.minus(3,

2)calc.multi(2,

2)--

->21

4

可以在這行**中吧這個cls打出來看看是個什麼東西,最為對比,同樣也加上列印self

<__main__.calc object at 0x1033ef4d0>
這樣對比出來就非常清晰了。cls指的是這個類,如果嚴謹一點可以再加上print calc。而self是這個類的乙個例項,是放在記憶體中的。

那麼這個到底有什麼用呢?說實話,一般來說沒什麼卵用,跟@staticmethod一樣。可以在不需要例項化的時候呼叫這個方法。

劃重點

如果你需要經常對函式的結構進行修改,那麼這個方法就非常有用了。

英文好的可以看這裡meaning of @classmethod and @staticmethod for beginner?

英文不好的就看這裡python 中的 classmethod 和 staticmethod 有什麼具體用途? - 水中柳影的回答 - 知乎

理解了selfcls是什麼時候,可以繼續再研究例項化的過程。

python在例項化的過程中,會首先呼叫__new__這個內建的方法。如果我們重寫這個方法,但是不按照原有的方式去寫,那麼就會例項化失敗,比如這樣:

class

calc

(object):

def__init__

(self)

:print

"class init..."

def__new__

(cls,

*args,

**kwargs)

:print

"new a class..."

defadd

(self, x, y)

:print x + y

if __name__ ==

'__main__'

: calc = calc(

)print calc -

-->

new a class..

.none

可以看到,例項化了乙個none出來。

__new__方法總增加return object.__new__(cls)即可正常例項化。同時可以看到__init__方法也被執行了。

特別說明一下,這個objectpython所有的新式類的基類。

了解了這些內容,重新來看看單例模式。之前介紹了乙個不嚴謹的單例,這裡來看乙個比較嚴謹的單例示例。

class

single

(object):

def__new__

(cls,

*args,

**kwargs):if

nothasattr

(cls,

'_single'):

cls._single =

object

.__new__(cls,

*args,

**kwargs)

return cls._single

這裡可以看到在__new__方法中加了乙個判斷,如果類例項化的時候沒有_single這個屬性,說明類還沒有被例項化,這個時候就按照正常的方法例項化,如果發現有_single這個屬性了,那麼就直接返回類的_single物件,也就是已經被例項化的物件,通過這個邏輯來保證例項化的時候,只會存在乙個例項。

從pyh看Python的工廠模式

設想 1 編寫各種tag型別,如head title body 2 過載 運算,實現類似html head的功能 想到第一點,當時就覺得繁瑣,要定義如此多個類 原諒我當時傻傻的 後來發現個開源專案 pyh工廠模式解析 pyh就乙個原始碼pyh.py,很簡單,以下擷取部分 分析,請尊重原作者,不要直接...

從「土豆」看軟體

之所以用 代替,是因為我認為軟體設計 開發測試等方面太多了,我只說軟體需求這一方面。上篇文章中提到兩個 買土豆的故事 故事一中的張三和故事二中的甲,都屬於 聰明 的人,他們為老闆想得周到,老闆一句 看看市場上有賣土豆的嗎?和一句 買點土豆回來。引發了張 李和甲乙的不同的反應。但是給人比較統一的感覺就...

從積木看專案

培訓多少是有些枯燥的,印象中那些關於專案管理的培訓大多是乙個經驗豐富的資深人士以授課或者討論的方式向在座的學員傳授知識 心得或者一些實踐技巧。最近參加了一堂別開生面的專案開發實踐課 樂高遊戲體驗 從名字上就能看出來,其實是在玩樂高積木,如果拋開遊戲背後的東西,單純玩玩積木也是很有意思的一件事,哈哈。...