python中 __new__和__init__
python这两个函数和类的实例化有关。
__init__是实例化完成之后调用的,会对生成的对象实例做一些修饰
__new__是python新类型才有的,它更像是c/c++里面的构造函数,因为这个函数会返回一个合法的实例。
看下面的例子
>>> class A(object): ... pass ... >>> class B(A): ... def __init__(self): ... print '__init__ running' ... def __new__(cls,*args, **kwargs): ... print "new %s" %cls ... print '__new__ running' ... return object.__new__(A, *args, **kwargs)
我们先生成了一个类A, 然后根据类A生成了一个类B。 注意B中定义了 __init__函数,它什么也没敢,只是打印一句话证明自己在运行,当然你可以在里面加一些别的操作。 而__new__函数就需要仔细注意一下了。这个__new__函数显示打印了当前的cls。 这个cls是像self一样在调用的时候不需要显示传给的。cls是当前的类,我们在__new__中把将其打印出来,这样你就能更直观的明白cls是什么。 然后我们打印一句话证明__new__在运行,再然后我们调用 object的new来返回一个值。注意这里调用的第一个参数是A,也就是说返回的对象是类型A的。
然后我们运行一下下面的代码。
1 2 3 | >>> b = B() new < class '__main__.B' > __new__ running |
b=B() 会调用B中的__new__()。 两行输出我们可以看到。但是我们知道__init__函数是在实例化之后被调用的,这里似乎没有调用__init__。 这是为什么呢? 因为我们B类中的__new__返回的类型是A类型。 __new__如果返回的不是当前类 cls 的实例,那么 __init__ 是不会被调用的。 我之前想,也许因为返回的是A类型的实例,那么如果A类型有__init__ 也许就会调用A类型的__init__。 事实证明也不会。
ok.我们把B类改一下,让其__new__返回cls 也就是当前类的实例。
1 2 3 4 5 6 7 8 9 10 11 12 | >>> class B(A): ... def __init__( self ): ... print '__init__ running' ... def __new__( cls , * args, * * kwargs): ... print "new %s" % cls ... print '__new__ running' ... return object .__new__( cls , * args, * * kwargs) ... >>> b = B() new < class '__main__.B' > __new__ running __init__ running |
可以看到是 __new__先运行 然后 __init__运行。 从这里也可以知道 __new__更类似于构造函数,而__init__只是在实例化之后用来修饰实例的
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 现代计算机视觉入门之:什么是图片特征编码
· .NET 9 new features-C#13新的锁类型和语义
· Linux系统下SQL Server数据库镜像配置全流程详解
· 现代计算机视觉入门之:什么是视频
· 你所不知道的 C/C++ 宏知识
· 不到万不得已,千万不要去外包
· C# WebAPI 插件热插拔(持续更新中)
· 会议真的有必要吗?我们产品开发9年了,但从来没开过会
· 【译】我们最喜欢的2024年的 Visual Studio 新功能
· 如何打造一个高并发系统?