通過上一篇的內(nèi)容,我們已經(jīng)知道定義一個類時,我們經(jīng)常會通過 __init__(self)
的方法在實例化對象的時候,對屬性進(jìn)行設(shè)置。比如下面的例子:
#!/usr/bin/env python3
# -*- coding: UTF-8 -*-
class User(object):
def __init__(self, name, age):
self.name = name;
self.age = age;
user=User('兩點水',23)
實際上,創(chuàng)建一個類的過程是分為兩步的,一步是創(chuàng)建類的對象,還有一步就是對類進(jìn)行初始化。__new__
是用來創(chuàng)建類并返回這個類的實例, 而__init__
只是將傳入的參數(shù)來初始化該實例.__new__
在創(chuàng)建一個實例的過程中必定會被調(diào)用,但 __init__
就不一定,比如通過pickle.load 的方式反序列化一個實例時就不會調(diào)用 __init__
方法。
def __new__(cls)
是在 def __init__(self)
方法之前調(diào)用的,作用是返回一個實例對象。還有一點需要注意的是:__new__
方法總是需要返回該類的一個實例,而 __init__
不能返回除了 None
的任何值
具體的示例:
#!/usr/bin/env python3
# -*- coding: UTF-8 -*-
class User(object):
def __new__(cls, *args, **kwargs):
# 打印 __new__方法中的相關(guān)信息
print('調(diào)用了 def __new__ 方法')
print(args)
# 最后返回父類的方法
return super(User, cls).__new__(cls)
def __init__(self, name, age):
print('調(diào)用了 def __init__ 方法')
self.name = name
self.age = age
if __name__ == '__main__':
usr = User('兩點水', 23)
看看輸出的結(jié)果:
調(diào)用了 def __new__ 方法
('兩點水', 23)
調(diào)用了 def __init__ 方法
通過打印的結(jié)果來看,我們就可以知道一個類創(chuàng)建的過程是怎樣的了,先是調(diào)用了 __new__
方法來創(chuàng)建一個對象,把參數(shù)傳給 __init__
方法進(jìn)行實例化。
其實在實際開發(fā)中,很少會用到 __new__
方法,除非你希望能夠控制類的創(chuàng)建。通常講到 __new__
,都是牽扯到 metaclass
(元類)的。
當(dāng)然當(dāng)一個對象的生命周期結(jié)束的時候,析構(gòu)函數(shù) __del__
方法會被調(diào)用。但是這個方法是 Python 自己對對象進(jìn)行垃圾回收的。