這兩個魔法函數是最容易混淆,面試官也經常會問到的知識點。咱們掌握區別以及原理,
就可以自信說:來呀,我不怕.
class User:
def __new__(cls, *args, **kwargs):
print("new")
def __init__(self,name):
self.name=name
print("init")
user=User()
打印結果:
new
通過上邊你可以發現兩個問題.
1.第一沒有傳參數居然沒有報錯.
2.沒有打印出 init 這句話.
解答下
1.new的功能是在生成對象之前所做的動作,接受的參數是cls 類
2.init是在對象生成之後完善對象的屬性 它接受的是self 對象
3.對象生成是在 new 裏面 return (返回一個對象)
我們用代碼解釋這個三點,
new的功能是在生成對象之前所做的動作.
class User:
def __new__(cls, *args, **kwargs):
print("new")
def __init__(self,name):
self.name=name
print("init")
print(type(User("body")))
打印結果:
new
<class 'NoneType'> #
雖然我們用 User(“body”))實例化了但是打印結果爲none type ,根本不是一個對象.
原因是我們在 new 沒有返回任何對象. 故稱爲在實例化對象之前的動作.
對象生成是在 new 裏面 return (返回一個對象)
我們在 new 返回一個對象,並打印對象type 是不是咱們預期的結果
class User:
def __new__(cls, *args, **kwargs):
print("new")
return super().__new__(cls)
print(type(User("body")))
pass
打印結果;
new
<class '__main__.User'>
我們調用了 父類的返回對象的方法return. 正如咱們所料 真的可以生成了對象.
有了對象以後 init 該幹活了.
.init是在對象生成之後完善對象的屬性
class User:
def __new__(cls, *args, **kwargs):
print("new")
return super().__new__(cls)
def __init__(self,name):
self.name=name
print("init")
print(type(User("body")))
pass
打印結果:
new
init
<class '__main__.User'>
init這個方法,只要有對象立馬就執行.它執行的步驟是:
1.new 有兩個類型的參數*args, **kwargs ,這個兩參數如何用,我已經在getattr已經介紹
不懂得可以翻翻 , args 接受tupe, kwargs 接受 dict ,例如:User(“body”,name=“andy”)
new方法會保存傳入參數在 對象裏.
看下代碼:
args = {tuple} <class 'tuple'>: ('body',)
kwargs = {dict} {'name': 'andy'}
2.當遇到 init的時候會 把保存數據 傳入 init並保存在屬性裏. 順序不能變哦
3.當new 保存的數據,加入 intit 沒有定義任何屬性,會報錯的,自己可以試試
說明 我對象有這些數據 ,你init 居然不完善這些屬性,我死給你看. 哈哈
它的用處是在元類編程裏大量的使用,以後講自定義元類也有這部分涉及,
但是絕大部分是不需要重寫new 這個函數.