python3:__new__和__init__魔法函数区别

版权声明:转载 或者复制请标注来源 https://blog.csdn.net/qq_34979346/article/details/83744950

这两个魔法函数是最容易混淆,面试官也经常会问到的知识点。咱们掌握区别以及原理,
就可以自信说:来呀,我不怕.

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 这个函数.

猜你喜欢

转载自blog.csdn.net/qq_34979346/article/details/83744950