_new_()与_init_()的区别

本文深入探讨Python中__new__与__init__方法的区别,包括它们的用途、参数、返回值及执行流程。并讨论了__new__在继承不可变类和实现单例模式中的应用。

先上代码 

    其中,__new__()不是一定要有,只有继承自object的类才有,该方法可以return父类(通过super(当前类名, cls).__new__())出来的实例,或者直接是object的__new__出来的实例。值得注意的是,在定义子类时没有重新定义__new__()时,Python默认调用该类父类的__new__()方法来构造该类实例,如果该类父类也没有重写__new__(),那么将一直追溯至object的__new__()方法,因为object是所有新式类的基类。如果子类中重写了__new__()方法,那么可以自由选择任意一个其他的新式类。

  可见,当类中同时出现__new__()和__init__()时,先调用__new__(),再调用__init__(),具体的执行过程为:

  1. 调用实例对象代码xiaoming = Student('xiaoming',175);

  2. 传入name和height的参数,执行Student类的__new__()方法,该方法返回一个类的实例,通常会用父类super(Student,cls).__new__(cls),__new__()产生的实例即__init__()的self;

  3. 用实例来调用__init__()方法,进行初始化实例对象的操作。

  可以看到,python中__new__()与__init__()的区别,

  1.首先用法不同,__new__()用于创建实例,所以该方法是在实例创建之前被调用,它是类级别的方法,是个静态方法;

            而 __init__() 用于初始化实例,所以该方法是在实例对象创建后被调用,它是实例级别的方法,用于设置对象属性的一些初始值。

  由此可知,__new__()在__init__() 之前被调用。如果__new__() 创建的是当前类的实例,会自动调用__init__()函数,通过return调用的__new__()的参数cls来保证是当前类实例,如果是其他类的类名,那么创建返回的是其他类实例,就不会调用当前类的__init__()函数。

 

  2.其次传入参数不同

  __new__()至少有一个参数cls,代表当前类,此参数在实例化时由Python解释器自动识别;

  __init__()至少有一个参数self,就是这个__new__()返回的实例,__init__()在__new__()的基础上完成一些初始化的操作。

 

  3.返回值不同

  __new__()必须有返回值,返回实例对象;

  __init__()不需要返回值。

  

  另外谈谈__new__()的作用,__new__()方法主要用于继承一些不可变的class,比如int, str, tuple, 提供一个自定义这些类的实例化过程的途径,一般通过重载__new__()方法来实现。代码如下

  另外__new__()方法还可以用来实现单例模式,也就是使每次实例化时只返回同一个实例对象。

在Python里,`__new__``__init__`方法有着不同的作用。`__new__`是构造器,负责创建类的实例;而`__init__`是初始化器,负责对已创建的实例进行初始化[^2]。 Python新类允许用户重载`__new__`和`__init__`方法。下面是一个新类的示例代码: ```python class newStyleClass(object): def __new__(cls): print("__new__ is called") return super(newStyleClass, cls).__new__(cls) def __init__(self): print("__init__ is called") print("self is: ", self) newStyleClass() ``` 运行上述代码,输出结果会显示先调用`__new__`方法,再调用`__init__`方法,如下: ```plaintext __new__ is called __init__ is called self is: <__main__.newStyleClass object at 0x...> ``` 这表明`__new__`先创建实例,之后`__init__`对该实例进行初始化[^2]。 再看另一个对比代码示例: ```python class B(): def __new__(cls): print("__new__方法被执行") def __init__(self): print("__init__方法被执行") b = B() class B(): def __new__(cls): print("__new__方法被执行") return super(B, cls).__new__(cls) def __init__(self): print("__init__方法被执行") b = B() ``` 在第一个`B`类中,`__new__`方法没有返回实例对象,因此`__init__`方法不会被调用;而在第二个`B`类中,`__new__`方法返回了实例对象,`__init__`方法会被正常调用。这进一步说明了`__new__`方法要返回实例对象,`__init__`方法才会发挥作用[^3]。 还有一个实例: ```python class A(): def __new__(cls, *args, **kwargs): print('this is A __new__') return object.__new__(cls) def __init__(self, title): print('this is A __init__') self.title = title a = A('python book') ``` 在这个例子中,`__new__`方法创建了实例,`__init__`方法对实例的`title`属性进行了初始化[^5]。 对于使用这两个方法,有几点建议:优先使用`__init__`,除非需要控制实例的创建过程,否则无需重写`__new__`;谨慎重写`__new__`,因为它会影响对象创建的核心逻辑,容易引入隐蔽的Bug;要理解二者的协作关系,它们共同完成对象从创建到初始化的完整流程[^4]。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值