天天看點

python 中__init__ ,__new__ ,__call__,__del__ 方法

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

https://www.cnblogs.com/34fj/p/6358702.html

https://segmentfault.com/a/1190000007256392(這篇對魔術方法介紹的很詳細)