python的__new__ 和 __init__

昨天偶然在一篇博客中看到关于 __new__ 和 __init__ 的一道题目,发现不太理解,于是搜了一下相关资料学习一下。

然后在博客园一篇博文评论区,与一位博主讨论了很多次,

链接 : Python中__new__的作用

想要弄清楚这两个方法具体的运行顺序以及机制 ,于是就写了一个简单的测试例子:

python版本:3.7 



class PositiveInteger(int):
    def __init__(self, value):
        print('init', value)
        # 没有返回值 , 只是为了对照
        super_init = super(PositiveInteger, self).__init__()
        print('super_init', super_init)

    def __new__(cls, value):
        print('new', value)
        value += 1
        super_new = super(PositiveInteger, cls).__new__(cls, value)
        print('super_new', super_new)
        return super_new


class PositiveInteger2(PositiveInteger):
    def __init__(self, value):
        print('init2', value)
        # 没有返回值 , 只是为了对照
        super_init2 = super(PositiveInteger2, self).__init__(abs(value))
        print('super_init2', super_init2)

    def __new__(cls, value):
        print('new2', value)
        value += 1
        super_new2 = super(PositiveInteger2, cls).__new__(cls, value)
        print('super_new2', super_new2)
        return super_new2


i = PositiveInteger2(-3)
print(i)

运行结果:

new2 -3
new -2
super_new -1
super_new2 -1
init2 -3
init 3
super_init None
super_init2 None
-1

这个例子可以很清晰追踪到,两个方法的执行顺序 ,以及继承时的调用顺序。

可以得出几点结论:

1. 声明对象时 , 会分别调用 __new__() 和 __init__() 方法 ,

2. 虽然__new__()先执行 , 但两个方法的入参变量是同一个对象 , __new__()中对入参进行二次赋值 , 并不会影响__init__()方法的入参对象值

3. 由于第二点 , 所以两个方法的入参数量需保持一致

4. __new__()方法创造了对象的实例并返回,而__init__() 方法作为构造方法对成员变量(局部变量) 进行操作 , __new__() 中无法触达局部变量 ( 这点在代码中没有显示 , 可以随便添加一个局部变量 , 在__new__() 调用试试看 , 编译器会报错 )

 

果然语言是想通的 , python的这种机制 , 和java的new关键字与类构造方法的关系很相似。

 

你可能感兴趣的:(python)