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