您的位置:首页 > 编程语言 > Python开发

python3中的 __new__() 与 __init__()

2020-02-17 04:25 309 查看

参考博客: (翻译版) https://blog.csdn.net/luoweifu/article/details/82732313

参考博客 (原版): https://spyhce.com/blog/understanding-new-and-init

python3中的
__new__()
__init__()

一个思考问题: 下面一行代码会发生什么?

p = Person()

以下内容都是依据python3中的运行结果说明

我们根据代码内容来讲解

  1. 简单的函数__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__函数接收实例为参数, 进行实例对象的初始化, 在类实例化对象的时候被调用

  1. __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__函数用于初始化实例

  1. 一个稍微复杂一点的测试

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__函数参数的地址是一样的

  1. 一个稍微神奇的测试

如果__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
  • 收藏
  • 分享
  • 文章举报
子狼 发布了7 篇原创文章 · 获赞 10 · 访问量 417 私信 关注
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: