python new和init的区别_python中_new_()与_init_()的区别

__new__方法的使用

只有继承于object的新式类才能有__new__方法,__new__方法在创建类实例对象时由Python解释器自动调用,一般不用自己定义,Python默认调用该类的直接父类的__new__方法来构造该类的实例,如果该类的父类也没有重写__new__,那么将一直按此规矩追溯至object的__new__方法,因为object是所有新式类的基类,若需要自定义__new__方法,一般用法如下:

classPerson(object):def __new__(cls):return object.__new__(cls)

__new__至少要有一个参数cls,代表要实例化的类,此参数在实例化时由Python解释器自动提供;__new__必须要有返回值,返回实例化出来的实例,可以return父类new出来的实例,或直接是object的new出来的实例。

object.new(cls)执行完返回的结果为Person类的实例对象,如下:

classPerson(object):def __init__(self):print("__init__")

self.name="张三"

def __new__(cls):print('__new__')

ob= object.__new__(cls)#ob为Person实例对象

print(ob)returnob

p1=Person()print(p1.name)

p1=Person()该语句主要做了以下工作:

首先调用Person的__new__方法,该方法通过object.new(cls)创建了Person实例对象,并返回。最后调用了该Person实例对象的__init__方法。

object.new()方法接收的参数是类对象,可以不是当前类对象cls,如果将cls换成其他类对象会发生什么呢,看下面代码的运行结果:

classDog(object):def __init__(self):

self.name="旺财"

print("Dog.__init__")classPerson(object):def __init__(self):

self.name="张三"

print("Person.__init__")def __new__(cls):print('__new__')

ob= object.__new__(Dog)returnob

p1=Person()print(type(p1))

由结果得知p1是Dog类的实例,但是有个问题,Python解释器没有自动执行__init__方法,由结果可以看出并没有打印字符串__init__。若__new__()没有正确返回当前类cls的实例,那__init__()将不会被调用。 我们可以在__new__方法中手动调用__init__方法(实际开发中好像没什么用)

classDog(object):def __init__(self):

self.name="旺财"

print("__init__")classPerson(object):def __init__(self):

self.name="张三"

print("__init__")def __new__(cls):print('__new__')

ob= object.__new__(Dog)

ob.__init__()returnob

p1=Person()print(type(p1))print(p1.name)

使用魔术方法__new__计算在创建实例的时候调用累加方法

如下场景:

假设我有一个学生类和一个班级类,想要实现的功能为:

执行班级人数增加的操作、获得班级的总人数;

学生类继承自班级类,每实例化一个学生,班级人数都能增加;

最后,我想定义一些学生,获得班级中的总人数。

思考:这个问题用类方法做比较合适,为什么?因为我实例化的是学生,但是如果我从学生这一个实例中获得班级总人数,在逻辑上显然是不合理的。同时,如果想要获得班级总人数,如果生成一个班级的实例也是没有必要的。

classClassTest(object):__num =0

@classmethoddefaddNum(cls):

cls.__num += 1@classmethoddefgetNum(cls):return cls.__num

#这里我用到魔术方法__new__,主要是为了在创建实例的时候调用累加方法。

def __new__(self):

ClassTest.addNum()return super(ClassTest, self).__new__(self)classStudent(ClassTest):def __init__(self):

self.name= ''a=Student()

b=Student()print(ClassTest.getNum())

_new_()与_init_()的区别

可见,当类中同时出现__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__()方法还可以用来实现单例模式,也就是使每次实例化时只返回同一个实例对象。

  • 1
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值