在__new__中修改kwargs没有作用于__init__

来源:8-4 __new__和__init__的区别

大野和我3326249

2018-10-30

图片描述
如上图demo中,我在__new__魔法函数中修改了kwargs, 但是似乎并没有作用于__init__构造函数里面
程序运行的结果为
图片描述
在__new__方法里的 kwargs 与 __init__的 kwargs的ID一致 ,__new__方法先于 __init__方法被调用 为什么会出现这种现象呢?

写回答

5回答

pineryme

2018-10-31

这是我理解class创建实例的调用流程,细节方面肯定有很多不对之处,但是通过断点调试,调用顺序就是这样。

//img.mukewang.com/szimg/5bd9b0930001fae504860488.jpg

//img.mukewang.com/szimg/5bd9b0c00001f5a302800176.jpg

如果不释放的那上层调用者entry的kwargs的id应该和init和new中的id是一样的。这里正好相差4,应该是类似于其他语言的函数调用栈。

new应该是创建对象,而init是初始化对象。这里甚至可以不设置init,而是使用__new__中代码初始化变量,比如如下代码:

//img.mukewang.com/szimg/5bd9b1e80001c8c303010309.jpg


0
1
大野和我3326249
非常感谢!
2018-11-01
共1条回复

慕运维5049730

2018-11-05

回答的很好,很厉害

0
2
慕运维5049730
再给我自己点个赞
2018-11-05
共2条回复

pineryme

2018-11-01

这里可以截图,再来发一个实验,哈哈哈:

//img.mukewang.com/szimg/5bda791400012dd403120356.jpg

执行结果如下:

//img.mukewang.com/szimg/5bda79330001242301920083.jpg

**kwargs是形参,kwargs是实参。

0
4
大野和我3326249
感谢大神耐心解答
2018-11-01
共4条回复

Jazz_Qi

2018-11-01

反正我也没懂,两个函数都是用同一个形参,但是两个函数是有先后运行的循序,在调用父类的__new__()前先把形参的内容修改应该影响实例化的过程,但结果是没有任何改变。我猜想这是python的策略,不给修改传入的参数。实现过程很可能是,函数中**kwargs所生成的字典是一回事,__new__和__init__中传入的参数是另一回事,前者是一种方便程序员编程的设计,后者是类实例化和编译过程更底层的策略造成的(可能根本没有用到那个字典),实际为何需要老师和高手解答。

0
0

pineryme

2018-10-30

//img.mukewang.com/szimg/5bd868fa0001811702380231.jpg

实际上__new__和__init__的调用流程应该是类似如上,super().__new__()并不会调用__init__(),可以自己用print语句测试一下,所以new中的kwargs在调用完成之后就释放了,当之后再调用init时kwargs重新分配,所以两者的地址恰好相等,但是此时的kwargs和new中的kwargs已经不是同一个kwargs了。

简单的测试一下:

a = {'a': 1}
print(id(a))

del a
try:
   print(a)
except NameError:
   pass

a = {'a': 2}
print(id(a))

两次的地址是一样的,但是两次的变量已经不是同一个变量了。

0
19
大野和我3326249
回复
pineryme
哈哈哈 谢谢你啦
2018-11-01
共19条回复

Python3高级核心技术97讲,高级进阶的必学课程

socket编程/多线程/多进程/线程池/asyncio并发编程/协程和异步IO

2121 学习 · 551 问题

查看课程