python3中的 __new__() 与 __init__()
参考博客: (翻译版) https://blog.csdn.net/luoweifu/article/details/82732313
参考博客 (原版): https://spyhce.com/blog/understanding-new-and-init
python3中的 __new__()
与 __init__()
一个思考问题: 下面一行代码会发生什么?
p = Person()
以下内容都是依据python3中的运行结果说明
我们根据代码内容来讲解
- 简单的函数__init__函数
class Person: def __init__(self): print("this is a init functione") def __str__(self): return "this is Person str" p = Person()print(p)
输出:
this is a init functione this is Person str
这是一个很普通的对象定义, __init__函数接收实例为参数, 进行实例对象的初始化, 在类实例化对象的时候被调用
- __new__函数的简单加入
class Person: def __new__(cls, *args, **kwargs): print("this is a new function") return super(Person, cls).__new__(cls) def __init__(self): print("this is a init functione") def __str__(self): return "this is Person str" p = Person()print(p)
输出:
this is a new function this is a init functione this is Person str
这也是个不难理解的对象定义, __new__函数为对象函数, 接收对象类型为参数, 产生一个对象的实例, 在调用类名进行实例化的时候被调用, 很明显, 比__init__函数先调用(如果文字描述很难理解,自己测试输出就好了)
或者我们来看objec对象中这两个函数的docstring
@staticmethod # known case of __new__ def __new__(cls, *more): # known special case of object.__new__ """ Create and return a new object. See help(type) for accurate signature. """ pass def __init__(self): # known special case of object.__init__ """ Initialize self. See help(type(self)) for accurate signature. """ pass
__new__函数的@staticmethod说明这是一个类方法而不是实例方法, 而__init__用self作为参数属于实例方法.
从docstring中可以知道, __new__函数用于创建并且返回一个对象实例, __init__函数用于初始化实例
- 一个稍微复杂一点的测试
new函数干了什么?返回了什么?返回这个有什么用?
不如我们测试一下不给new函数返回值,会发生什么?
class Person: def __new__(cls, *args, **kwargs): print("this is a new function") # return super(Person, cls).__new__(cls) def __init__(self): print("this is a init functione") def __str__(self): return "this is Person str" p = Person()print(p)
输出
this is a new function None
这里我们发现, 如果我们不给__new__函数返回值(或者说给__new__函数返回None), __init__函数根本不会执行, 也不难理解, 因为__new__函数用于创建并返回实例化对象, 如果没有返回, self就不存在, init函数没有参数可以接受自然不会执行,我们可以猜测new函数返回的实例化对象传递给了init函数
验证一下
Person.__new__()的返回值:
class Person: def __new__(cls, *args, **kwargs): print("this is a Person new function") t = super(Person, cls).__new__(cls) print(id(t)) return t def __init__(self): print("init: id=", id(self)) print("this is a Person init functione") def __str__(self): return "this is Person str" p = Person()print(p) print(type(p)) print("id(p) = ", id(p))
输出
this is a Person new function 2129091660152 init: id= 2129091660152 this is a Person init functione this is Person str <class '__main__.Person'> id(p) = 2129091660152
对象p的地址与__new__函数的返回值以及__new__函数参数的地址是一样的
- 一个稍微神奇的测试
如果__new__函数必须返回一个对象, 那如果返回的不是本类对象呢?
试试
class Person: def __new__(cls, *args, **kwargs): print("this is a new function") return 233 def __init__(self): print("this is a init functione") def __str__(self): return "this is Person str" p = Person()print(p) print(type(p))
输出
this is a new function 233 <class 'int'>
这里可以发现, p的地址有内容,但是不是Person类,而且Person类没有进行__init__函数,那么执行了哪个对象的初始化函数呢?
class Test: def __new__(cls, *args, **kwargs): print("this a Test new function") t = super(Test, cls).__new__(cls) print("Test id:", id(t)) return t def __init__(self): print("this a Test init function") def __str__(self): return "this is Test str" class Person: def __new__(cls, *args, **kwargs): print("this is a Person new function") t = super(Person, cls).__new__(cls) print("Person id: ", id(t)) return Test() def __init__(self): print("init: id=", id(self)) print("this is a Person init functione") def __str__(self): return "this is Person str" p = Person()print(p) print(type(p)) print("p id: ", id(p))
输出
this is a Person new function Person id: 2062107445680 this a Test new function Test id: 2062107445624 this a Test init function this is Test str <class '__main__.Test'> p id: 2062107445624
这里可以发现虽然p是用Person()创建的,但是由于
Person.__new__()函数返回的是一个Test()对象,所以p的类型也是Test, 其地址与
Test.__new__()的返回值一样,而且进行了
Test.__init__()初始化.
总结
p = Person()
当用类Person实例化一个对象的时候(如上面一行代码), 会先进行类函数
Person.__new__()进行对象的创建,并且返回一个对象object,这个实例的实例函数
object.__init__()随之被执行,并返回None(如果不是None会出现错误,可以试一下)
这就是这一行代码会发生的事情
- 点赞 1
- 收藏
- 分享
- 文章举报
- python函数修饰器
- cenos上面python3及mysql的安装
- 《Python3程序开发指南(第二版)》例题之多线程文件查找关键词
- python导入模块
- python实现用户好友推荐
- python基于item-item filtering实现话题推荐
- 用python爬取高考网历年高考分数线将数据放入MySQL并绘制图表
- 软件测试基础+测试开发+python+测试工具免费领取
- python自学中的我
- ZZULI 1015: 计算时间间隔 Python
- python起步——可变对象和不可变对象
- Gvim —— win 7 下 vim 环境配置 及python开发常用设置
- 使用python脚本提取OC中写死的字符串方便国际化
- python3利用pandas将csv文件中的数据导入mysql数据库
- 【Python基础操作】1.数据读取(csv,Excel,MySQL)
- Python3.6.2 图形界面模块Tk (Day1)
- 用python+tkinter写个校验和工具
- python selenium+pywin32 实现网页另存为
- python 输出所有大小写字母和0~9数字
- pycharm导入python包