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中的运行结果说明

我们根据代码内容来讲解

  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
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值