Python面試常見問題, init

2021-10-07 01:49:49 字數 3417 閱讀 7415

今天我們來聊聊python當中乙個新的預設函式__new__。

真假建構函式

如果你去面試python工程師的崗位,面試官問你,請問python當中的類的建構函式是什麼?

你不假思索,當然是__init__啦!如果你這麼回答,很有可能你就和offer無緣了。因為在python當中__init__並不是建構函式,new__才是。是不是有點蒙,多西得(日語:為什麼)?我們不是一直將__init__方法當做建構函式來用的嗎?怎麼又冒出來乙個__new,如果__new__才是建構函式,那麼為什麼我們建立類的時候從來不用它呢?

別著急,我們慢慢來看。首先我們回顧一下__init__的用法,我們隨便寫一段**:

class student:

definit(self, name, gender):

self.name = name

self.gender = gender

我們一直都是這麼用的,對不對,毫無問題。但是我們換乙個問題,我們在python當中怎麼實現單例(singleton)的設計模式呢?怎麼樣實現工廠呢?

從這個問題出發,你會發現只使用__init__函式是不可能完成的,因為__init__並不是建構函式,它只是初始化方法。也就是說在呼叫__init__之前,我們的例項就已經被建立好了,__init__只是為這個例項賦上了一些值。如果我們把建立例項的過程比喻成做乙個蛋糕,init__方法並不是烘焙蛋糕的,只是點綴蛋糕的。那麼顯然,在點綴之前必須先烘焙出乙個蛋糕來才行,那麼這個烘焙蛋糕的函式就是__new

__new__函式

我們來看下__new__這個函式的定義,我們在使用python物件導向的時候,一般都不會重構這個函式,而是使用python提供的預設建構函式,python預設建構函式的邏輯大概是這樣的:

defnew(cls, *args, **kwargs):

return super().new(cls, *args, **kwargs)

從**可以看得出來,函式當中基本上什麼也沒做,就原封不動地呼叫了父類的建構函式。這裡隱藏著python當中類的建立邏輯,是根據繼承關係一級一級建立的。根據邏輯關係,我們可以知道,當我們建立乙個例項的時候,實際上是先呼叫的__new__函式建立例項,然後再呼叫__init__對例項進行的初始化。我們可以簡單做個實驗:

class test:

defnew(cls):

print(『new』)

return object().new(cls)

definit(self):

print(『init』)

當我們建立test這個類的時候,通過輸出的順序就可以知道python內部的呼叫順序。

從結果上來看,和我們的推測完全一樣。

單例模式

那麼我們過載__new__函式可以做什麼呢?一般都是用來完成__init__無法完成的事情,比如前面說的單例模式,通過__new__函式就可以實現。我們來簡單實現一下:

class singletonobject:

defnew(cls, *args, **kwargs):

if not hasattr(singletonobject, 「_instance」):

singletonobject._instance = object.new(cls)

return singletonobject._instance

def __init__(self):

pass

當然,如果是在併發場景當中使用,還需要加上執行緒鎖防止併發問題,但邏輯是一樣的。

除了可以實現一些功能之外,還可以控制例項的建立。因為python當中是先呼叫的__new__再呼叫的__init__,所以如果當呼叫__new__的時候返回了none,那麼最後得到的結果也是none。通過這個特性,我們可以控制類的建立。比如設定條件,只有在滿足條件的時候才能正確建立例項,否則會返回乙個none。

比如我們想要建立乙個類,它是乙個int,但是不能為0值,我們就可以利用__new__的這個特性來實現:

class nonzero(int):

defnew(cls, value):

return super().new(cls, value) if value != 0 else none

那麼當我們用0值來建立它的時候就會得到乙個none,而不是乙個例項。

工廠模式

理解了__new__函式的特性之後,我們就可以靈活運用了。我們可以用它來實現許多其他的設計模式,比如大名鼎鼎經常使用的工廠模式。

所謂的工廠模式是指通過乙個介面,根據引數的取值來建立不同的例項。建立過程的邏輯對外封閉,使用者不必關係實現的邏輯。就好比乙個工廠可以生產多種零件,使用者並不關心生產的過程,只需要告知需要零件的種類。也因此稱為工廠模式。

比如說我們來建立一系列遊戲的類:

class last_of_us:

def play(self):

print(『the last of us is really funny』)

class uncharted:

def play(self):

print(『the uncharted is really funny』)

class psgame:

def play(self):

print(『ps has many games』)

然後這個時候我們希望可以通過乙個介面根據引數的不同返回不同的遊戲,如果不通過__new__,這段邏輯就只能寫成函式而不能通過物件導向來實現。通過過載__new__我們就可以很方便地用引數來獲取不同類的例項:

class gamefactory:

games =

defnew(cls, name):

if name in cls.games:

return cls.gamesname

else:

return psgame()

uncharted = gamefactory(『uncharted』)

last_of_us = gamefactory(『last_of_us』)

總結相信看到這裡,關於__new__這個函式的用法應該都能理解了。一般情況下我們是用不到這個函式的,只會在一些特殊的場景下使用。雖然如此,我們學會它並不只是用來實現設計模式,更重要的是可以加深我們對於python物件導向的理解。

除此之外,另乙個經常使用__new__場景是元類。所以今天的這篇文章其實也是為了後面介紹元類的其他用法打基礎。

面試常見問題

面試時,有幾個問題是公司面試人員常常會提出的,針對這些問題好好準備,在面試時也就不會啞口無言,無言以對了,下面就面試十大必考題做出分析,也許對hr經理也是乙個 1 為什麼想進本公司?這通常是面試官最先問到的問題。此時面試官就開始評斷錄用與否了,建議大家先判斷自己去應徵的工作性質,是專業能力導向呢,或...

面試常見問題

1.如果我們不能提供你所要求的薪水,你還願意來我們公司嗎?你的期望薪水是多少?你想得到的薪水是多 少?如果達不到你的要求,怎麼辦?答 我認為工作最重要的是合作開心,薪酬是其次的,不過我原來的月薪是 元,如果跳槽的話就希望 自己能有點進步,如果不是讓您太為難的話,您看這個工資是不是可以有一點提高?2....

面試常見問題

網線與集線器屬於物理層 網絡卡與交換機屬於資料鏈路層 路由器屬於網路層 防治方法 htmlspecialchars 轉義特殊字元為字元實體,strip tags 過濾html標籤,addslashes 可轉義單雙引號反斜槓null 在特殊字元前面加反斜槓進行轉義 防治方法 請求附加隨機token進行...