1. 程式人生 > >python 中__init__ ,__new__ ,__call__,__del__ 方法

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(這篇對魔術方法介紹的很詳細)