1.__new__(cls, *args, **kwargs) 建立物件時呼叫,返回當前物件的一個例項;注意:這裡的第一個引數是cls即class本身
2.__init__(self, *args, **kwargs) 建立完物件後呼叫,對當前物件的例項的一些初始化,無返回值,即在呼叫__new__之後,根據返回的例項初始化;注意,這裡的第一個引數是self即物件本身【注意和new的區別】
3.__call__(self, *args, **kwargs) 如果類實現了這個方法,相當於把這個型別的物件當作函式來使用,相當於 過載了括號運算子
看具體的例子:
class O(object):
def __init__(self, *args, **kwargs):
print "init"
super(O, self).__init__(*args, **kwargs)
def __new__(cls, *args, **kwargs):
print "new", cls
return super(O, cls).__new__(cls, *args, **kwargs)
def __call__(self, *args, **kwargs):
print "call"
oo = O()
print "________"
oo()
列印出來的是:
new
init
________
call
比如:Python Singleton(單例模式)實現,那我們是不是隻是過載一些__new__方法就可以了
class Singleton1(object):
""" 過載new方法"""
def __new__(cls, *args, **kwargs):
if not "_instance" in vars(cls):
cls._instance = super(Singleton1, cls).__new__(cls, *args, **kwargs)
return cls._instance
可不可以過載__init__方法呢?明顯不可以,因為__init__之前呼叫了__new__方法,這時候已經生成了一個物件了,沒辦法實現單例模式
注意1、__init__並不相當於C#中的建構函式,執行它的時候,例項已構造出來了。
1
2
3
4
5
|
class A( object ): def __init__( self ,name): self .name = name def getName( self ): return 'A ' + self .name |
當我們執行
1
|
a = A( 'hello' ) |
時,可以理解為
1
2
|
a = object .__new__(A) A.__init__(a, 'hello' ) |
即__init__作用是初始化已例項化後的物件。
注意2、子類可以不重寫__init__,例項化子類時,會自動呼叫超類中已定義的__init__
1
2
3
4
5
6
7
|
class B(A): def getName( self ): return 'B ' + self .name if __name__ = = '__main__' : b = B( 'hello' ) print b.getName() |
但如果重寫了__init__,例項化子類時,則不會隱式的再去呼叫超類中已定義的__init__
1
2
3
4
5
6
7
8
9
|
class C(A): def __init__( self ): pass def getName( self ): return 'C ' + self .name if __name__ = = '__main__' : c = C() print c.getName() |
則會報"AttributeError: 'C' object has no attribute 'name'”錯誤,所以如果重寫了__init__,為了能使用或擴充套件超類中的行為,最好顯式的呼叫超類的__init__方法
1
2
3
4
5
6
7
8
9
|
class C(A): def __init__( self ,name): super (C, self ).__init__(name) def getName( self ): return 'C ' + self .name if __name__ = = '__main__' : c = C( 'hello' ) print c.getName() |