python3:__new__和__init__魔法函數區別

這兩個魔法函數是最容易混淆,面試官也經常會問到的知識點。咱們掌握區別以及原理,
就可以自信說:來呀,我不怕.

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 這個函數.

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章