python 中__init__ ,__new__ ,__call__,__del__ 方法
阿新 • • 發佈:2018-11-21
python 中__init__
,__new__
,__call__
,__del__
方法
三個方法的作用
__new__ 負責建立一個例項物件
__init__ 負責將該例項物件初始化
__call__ 使例項能夠像函式一樣被呼叫,同時不影響例項本身的生命週期(__call__()不影響一個例項的構造和析構)。但是__call__()可以用來改變例項的內部成員的值。
__init__()
負責初始化, 在Python中,__init__()函式的意義等同於類的構造器(同理,__del__()等同於類的解構函式)。因此,__init__()方法的作用是建立一個類的例項
###__call__()
在Python中, 函式其實就是物件, 所有的函式都是一級物件, 也叫可呼叫物件, 這意味著Python中的函式的引用可以作為輸入傳遞到其他的函式/方法中,並在其中被執行。 而Python中類的例項(物件)可以被當做函式對待。 一個類例項也可以變成一個可呼叫物件,只需要實現一個特殊方法__call__()。 也就是說,我們可以將它們作為輸入傳遞到其他的函式/方法中並呼叫他們,正如我們呼叫一個正常的函式那樣。而類中__call__()函式的意義正在於此。為了將一個類例項當做函式呼叫,我們需要在類中實現__call__()方法。也就是我們要在類中實現如下方法:def __call__(self, *args)。這個方法接受一定數量的變數作為輸入。 假設x是X類的一個例項。那麼呼叫x.__call__(1,2)等同於呼叫x(1,2)。這個例項本身在這裡相當於一個函式。
__del__
在物件的生命週期結束時, __del__會被呼叫,可以將__del__理解為"解構函式".
__del__定義的是當一個物件進行垃圾回收時候的行為。
有一點容易被人誤解, 實際上,x.__del__() 並不是對於del x的實現,但是往往執行del x時會呼叫x.__del__();
呼叫x.__del__, 並不會刪除這個物件, 但是如果你 del x,他會自動呼叫__del__方法, x這個物件就不存在了
__new__()
官方文件的說法, __new__方法主要是當你繼承一些不可變的class時(比如int, str, tuple), 提供給你一個自定義這些類的例項化過程的途徑。還有就是實現自定義的metaclass。 可以參考兩段程式碼 class PositiveInteger(int): def __init__(self, value): super(PositiveInteger, self).__init__(self, abs(value)) i = PositiveInteger(-3) print i 結果是 -3, 因為 int 是不可變的物件, 我們必須要過載__new__的方法才能起到自定義的作用 class PositiveInteger(int): def __new__(cls, value): return super(PositiveInteger, cls).__new__(cls, abs(value)) i = PositiveInteger(-3)
new方法可以做很多有趣的事情, 比如我最喜歡用new來實現單例模式
因為類每一次例項化後產生的過程都是通過__new__來控制的,所以通過過載__new__方法,我們 可以很簡單的實現單例模式
class ChromeDriver(object):
_instance = None
def __new__(cls, *args, **kw):
if not cls._instance:
cls._instance = super(ChromeDriver, cls).__new__(cls, *args, **kw)
return cls._instance
這是我在爬蟲中介軟體中加的一個chromedrive 中介軟體, 實現了單例模式, 因為如果不用單例我開多併發的話可能會導致例項很多瀏覽器, 造成伺服器壓力過大(因為瀏覽器很吃記憶體), 實現單例模式就可以避免這個問題, 只會例項一個瀏覽器來進行頁面請求.
單例模式
單例模式(Singleton Pattern)是一種常用的軟體設計模式,該模式的主要目的是確保某一個類只有一個例項存在。當你希望在整個系統中,某個類只能出現一個例項時,單例物件就能派上用場。
具體的python實現單例模式的幾種方法可以參考下面部落格:
https://www.cnblogs.com/huchong/p/8244279.html
不過, 我感覺應該用__new__來實現單例模式應該是比較簡單的一種了
比較
1 執行順序 __new__, __init__, __call__
2 __new__在建立一個例項的過程中必定會被呼叫,但__init__就不一定, __new__()決定是否要使用該__init__()方法,因為__new__()可以呼叫其他類的構造方法或者直接返回別的物件來作為本類 的例項。
3 __new__方法總是需要返回該類的一個例項,而__init__不能返回除了None的任何值。比如下面例子:
class Doo(object):
def __init__(self):
print('aa')
return None (TypeError: __init__() should return None, 只能返回None)
###參考文件:
https://www.cnblogs.com/superxuezhazha/p/5793536.html
https://blog.csdn.net/yaokai_assultmaster/article/details/70256621