1
2
3
4
5
6
7
8
|
class A( object ):
def __init__( self ):
print "init"
def __new__( cls , * args, * * kwargs):
print "new %s" % cls
return object .__new__( cls , * args, * * kwargs)
A()
|
輸出:html
new <class '__main__.A'>
initpython
知識點:安全
繼承自object的新式類纔有__new__框架
__new__至少要有一個參數cls,表明要實例化的類,此參數在實例化時由Python解釋器自動提供post
__new__必需要有返回值,返回實例化出來的實例,這點在本身實現__new__時要特別注意,能夠return父類__new__出來的實例,或者直接是object的__new__出來的實例url
__init__有一個參數self,就是這個__new__返回的實例,__init__在__new__的基礎上能夠完成一些其它初始化的動做,__init__不須要返回值spa
若__new__沒有正確返回當前類cls的實例,那__init__是不會被調用的,即便是父類的實例也不行設計
1
2
3
4
5
6
7
8
9
10
11
12
|
class A( object ):
pass
class B(A):
def __init__( self ):
print "init"
def __new__( cls , * args, * * kwargs):
print "new %s" % cls
return object .__new__(A, * args, * * kwargs) #返回了A的一個實例
b = B()
print type (b)
|
輸出:code
new <class '__main__.B'>
<class '__main__.A'>htm
詳細解釋可參考:
http://www.cnblogs.com/ifantastic/p/3175735.html
[Python] Python 之 __new__() 方法與實例化
__new__() 是在新式類中新出現的方法,它做用在構造方法建造實例以前,能夠這麼理解,在 Python 中存在於類裏面的構造方法 __init__() 負責將類的實例化,而在 __init__() 啓動以前,__new__() 決定是否要使用該 __init__() 方法,由於__new__() 能夠調用其餘類的構造方法或者直接返回別的對象來做爲本類的實例。
若是將類比喻爲工廠,那麼__init__()方法則是該工廠的生產工人,__init__()方法接受的初始化參數則是生產所需原料,__init__()方法會按照方法中的語句負責將原料加工成實例以供工廠出貨。而__new__()則是生產部經理,__new__()方法能夠決定是否將原料提供給該生產部工人,同時它還決定着出貨產品是否爲該生產部的產品,由於這名經理能夠借該工廠的名義向客戶出售徹底不是該工廠的產品。
__new__() 方法的特性:
- __new__() 方法是在類準備將自身實例化時調用。
- __new__() 方法始終都是類方法,即便沒有被加上類方法裝飾器。
- 類的實例化和它的構造方法一般都是這個樣子:
class MyClass(object):
def __init__(self, *args, **kwargs):
...
# 實例化
myclass = MyClass(*args, **kwargs)
正如以上所示,一個類能夠有多個位置參數和多個命名參數,而在實例化開始以後,在調用 __init__() 方法以前,Python 首先調用 __new__() 方法:
def __new__(cls, *args, **kwargs):
...
第一個參數cls是當前正在實例化的類。
- 若是要獲得當前類的實例,應當在當前類中的 __new__() 方法語句中調用當前類的父類的 __new__() 方法。
例如,若是當前類是直接繼承自 object,那當前類的 __new__() 方法返回的對象應該爲:
def __new__(cls, *args, **kwargs):
...
return object.__new__(cls)
注意:
事實上若是(新式)類中沒有重寫__new__()方法,即在定義新式類時沒有從新定義__new__()時,Python默認是調用該類的直接父類的__new__()方法來構造該類的實例,若是該類的父類也沒有重寫__new__(),那麼將一直按此規矩追溯至object的__new__()方法,由於object是全部新式類的基類。
而若是新式類中重寫了__new__()方法,那麼你能夠自由選擇任意一個的其餘的新式類(一定要是新式類,只有新式類一定都有__new__(),由於全部新式類都是object的後代,而經典類則沒有__new__()方法)的__new__()方法來製造實例【本身理解:實際上並非自由選擇任一個新式類,而是任意一個兄弟級別的新式類,由於全部兄弟的__new__()方法返回的都是同一個父類的__new__()方法,實際上也就是最終必須是用直接的父類的__new__()方法,不能用到爺爺級別的,也不能用到叔伯級別的】,包括這個新式類的全部前代類和後代類,只要它們不會形成遞歸死循環。具體看如下代碼解釋:
class Foo(object): def __init__(self, *args, **kwargs): ... def __new__(cls, *args, **kwargs): return object.__new__(cls, *args, **kwargs)
# 以上return等同於
# return object.__new__(Foo, *args, **kwargs)
# return Stranger.__new__(cls, *args, **kwargs)
# return Child.__new__(cls, *args, **kwargs)
class Child(Foo): def __new__(cls, *args, **kwargs): return object.__new__(cls, *args, **kwargs)
# 若是Child中沒有定義__new__()方法,那麼會自動調用其父類的__new__()方法來製造實例,即 Foo.__new__(cls, *args, **kwargs)。
# 在任何新式類的__new__()方法,不能調用自身的__new__()來製造實例,由於這會形成死循環。所以必須避免相似如下的寫法:
# 在Foo中避免:return Foo.__new__(cls, *args, **kwargs)或return cls.__new__(cls, *args, **kwargs)。Child同理。
# 使用object或者沒有血緣關係的新式類的__new__()是安全的,可是若是是在有繼承關係的兩個類之間,應避免互調形成死循環,例如:(Foo)return Child.__new__(cls), (Child)return Foo.__new__(cls)。
class Stranger(object): ...
# 在製造Stranger實例時,會自動調用 object.__new__(cls)
- 一般來講,新式類開始實例化時,__new__()方法會返回cls(cls指代當前類)的實例,而後該類的__init__()方法做爲構造方法會接收這個實例(即self)做爲本身的第一個參數,而後依次傳入__new__()方法中接收的位置參數和命名參數。
注意:若是__new__()沒有返回cls(即當前類)的實例,那麼當前類的__init__()方法是不會被調用的。若是__new__()返回其餘類(新式類或經典類都可)的實例,那麼只會調用被返回的那個類的構造方法【本身實際操做了一下,返回的是其餘類的實例,可是並無調用其餘的那個類的構造方法__init__()】。
class Foo(object): def __init__(self, *args, **kwargs): ... def __new__(cls, *args, **kwargs): return object.__new__(Stranger, *args, **kwargs) class Stranger(object): ... foo = Foo() print type(foo)
# 打印的結果顯示foo實際上是Stranger類的實例。
# 所以能夠這麼描述__new__()和__ini__()的區別,在新式類中__new__()纔是真正的實例化方法,爲類提供外殼製造出實例框架,而後調用該框架內的構造方法__init__()使其豐滿。
# 若是以建房子作比喻,__new__()方法負責開發地皮,打下地基,並將原料存放在工地。而__init__()方法負責從工地取材料建造出地皮開發招標書中規定的大樓,__init__()負責大樓的細節設計,建造,裝修使其可交付給客戶。