在python中建立乙個新式類時,一般都會定義乙個__init__
方法,用來對類的例項進行初始化。但是__init__
方法並不是類的構造方法,類中真正的構造方法是__new__
方法。
看看下面的例子:
class
test
:def
__init__
(self)
:print
('__init__ method in {}'
.format
(self.__class__)
)def
__new__
(cls,
*args,
**kwargs)
:print
('__new__ method in {}'
.format
(cls)
)return
super
(test, cls)
.__new__(cls,
*args,
**kwargs)
test = test(
)# 輸出為:
# __new__ method in
# __init__ method in
從上例可以看出,當例項化類時,類的__new__
方法先被呼叫,然後是__init__
方法。
一般來說, 類的__new__
方法和__init__
方法都會是下面的形式:
def
__new__
(cls,
*args,
**kwargs)
:# do something
obj =..
.return obj
def__init__
(self,
*args,
**kwargs)
:# do something
對於類的__new__
方法和__init__
方法可以概括為:
__new__
方法是新式類中的方法,它具有以下特性:
如果(新式)類中沒有重寫__new__
方法,預設是呼叫該類的直接父類的__new__
方法來建立類的例項。如果該類的父類也沒有重寫__new__
方法,那麼將一直按照繼承鏈向上追溯至object
類的__new__
方法。
如果(新式)類中重寫了__new__
方法,那麼可以選擇任意乙個其他新式類(必須是新式類,只有新式類有__new__
方法,因為object
類是所有新式類的基類)的__new__
方法來建立例項,其中包括這個新式類的父類和子孫類,只要它們不會造成遞迴死迴圈。
看看下面的例子:
class
animal
:def
__new__
(cls,
*args,
**kwargs)
: obj =
super
(animal, cls)
.__new__(cls,
*args,
**kwargs)
""" 這裡的super(animal, cls).__new__(cls, *args, **kwargs) 也可以寫成如下形式:
1. object.__new__(cls, *args, **kwargs)
2. object.__new__(animal, *args, **kwargs)
3. cat.__new__(cls, *args, **kwargs)
4. people.__new__(cls, *args, **kwargs) 即使people類和animal類沒有關係,也是可以呼叫的;
在任何新式類中,不能呼叫自身的 『__new__』 方法來建立例項,因為這樣會造成死迴圈。
所以要避免如下形式的呼叫:
return animal.__new__(cls, *args, **kwargs)
return cls.__new__(cls, *args, **kwargs)
"""print
('call __new__ method for {}'
.format
(obj.__class__)
)return obj
class
cat(animal)
:def
__new__
(cls,
*args,
**kwargs)
: obj =
object
.__new__(cls)
print
('call __new__ method for {}'
.format
(obj.__class__)
)return obj
class
people
:# 該類沒有 '__new__' 方法,那麼會自動呼叫其父類,即object類的 '__new__' 方法來建立例項。
pass
class
girl
:def
__new__
(cls,
*args,
**kwargs)
: obj =
object
.__new__(cat)
print
('call __new__ method for {}'
.format
(obj.__class__)
)return obj
dog = animal(
)cat = cat(
)tina = girl(
)# 輸出為:
# call __new__ method for
# call __new__ method for
# call __new__ method for
類的__new__
方法決定是否使用該類的__init__
方法,因為類的__new__
方法可以呼叫其他類的構造方法或者直接返回別的類例項作為本類的例項。
通常來說,新式類進行例項化時,__new__
方法會返回當前類的例項,然後呼叫該類的__init__
方法進行例項的初始化。但是,如果__new__
方法返回的不是當前類的例項,那麼,當前類的__init__
方法就不會被呼叫。
請看下面的例子:
classa:
def__init__
(self,
*args,
**kwargs)
:print
('call __init__ method from {}'
.format
(self.__class__)
)def
__new__
(cls,
*args,
**kwargs)
: obj =
super
(a, cls)
.__new__(cls,
*args,
**kwargs)
print
('call __new__ method for {}'
.format
(obj.__class__)
)return obj
classb:
def__init__
(self,
*args,
**kwargs)
:print
('call __init__ method from {}'
.format
(self.__class)
)def
__new__
(cls,
*args,
**kwargs)
: obj =
super
(b, cls)
.__new__(a,
*args,
**kwargs)
print
('call __new__ for {}'
.format
(obj.__class__)
)return obj
b = b(
)print
(type
(b))
# 輸出為:
# call __new__ for
#
可以看到,類b在例項化時並未呼叫自身的的初始化方法__init__
。因為類b的構造方法返回的是類a的例項。 靜態初始化塊 初始化塊 構造方法
1.所有的靜態初始化塊都優先執行,其次才是非靜態的初始化塊和建構函式,它們的執行順序是 1 父類的靜態初始化塊 2 子類的靜態初始化塊 3 父類的初始化塊 4 父類的建構函式 5 子類的初始化塊 6 子類的建構函式 注意 1 此處的構造方法需要與自己的類名相同,2 靜態 初始化塊需要用 2.構造方法...
物件構造和初始化
1 構造方法 物件都有構造方法,如果沒有,則新增乙個default方法 抽象類有構造方法 2 呼叫本類和父類 this 本類其他 super父類 父類所有構造方法都得到呼叫 例 classa class bextends a 不能通過編譯 1.class a a int a 2.classa3.cl...
建構函式初始化列表和初始化函式
其實並沒有所謂的初始化函式的概念,本文中的初始化函式只是說明在函式體內進行賦值。而初始化列表才是真正意義上的物件初始化。使用初始化列表效率會高一點。c 規定,物件的成員變數的初始化動作發生在進入建構函式本體之前。在建構函式體內只是賦值,並不是初始化。請看下面這個栗子 class base publi...