提到构造器,大家都会想到 __init__,那么__new__是什么?也是构造器。

 

init 构造器

都很熟悉了,直接上代码

class MyClass(object):
    def __init__(self):
        pass

    def m1(self):
        print(3)

mc = MyClass()
mc.m1()        # 3 

是不是很简单

别急,请跟着我的思路,方法m1的参数有个self,这个self就是实例,在调用m1之前这个实例肯定已经产生了;但是init的参数也有个self,在调用init之前,我们并没有实例化,那这个self从何而来呢?new生成的。

 

new 构造器

1. new 和 init 一样都是类的构造器

2. new在init之前执行,即使没有显示定义

3. new 必须有返回对象,这个对象就是该类的实例,或者父类的实例(该类继承了一个类),并且是new出来的实例,这个实例的就是self,也就是该类的实例化对象。

4. new生成的self传给init,如果没有正确返回实例,init将不会执行。

5. new可以自定义

6. new是类方法,需要显示的传入类cls作为第一个参数,至少要有这个参数

7. 新式类中才有new

8. new和init共用参数,也就是说二者参数形式要一致

几个例子来验证上面8条。

 

代码1

class A(object):
    def __init__(self,a):
        print "init"
        self.a=a
    def __new__(cls,*args, **kwargs):
        print "new %s"%cls
        print('args:', args)
        return object.__new__(cls, *args, **kwargs)     # 返回当前类的实例

aa=A(3)
# new <class '__main__.A'>
# ('args:', (3,))
# init
print(aa)       # <__main__.A object at 0x026FC4B0>   
print(aa.a)     # 3                                   self.a

1. 新式类,经典类我试了,不行,new没有运行,但不会报错

2. new 比 init 先执行

3. new 和 init 共用了参数3

4. new 返回了当前类的实例,new出来的

 

代码2

class inch(float):
    def __new__(cls, arg=0.0):    # cls 相当于 self
        print(1)
        return float.__new__(cls, arg * 0.0254)
    def __init__(self, aa):
        print('aa:', aa)
        print(2)

a = inch(12)    # new 和 init 公用了参数12
# 1
# ('aa:', 12)
# 2
print(a)    # 返回的实例就是new的return,父类的实例 float(12*0.0254)
# 0.3048    =12*0.0254

1. 该类继承了float类

2. new 返回了父类float的实例

3. 该类实例化后其实是new 返回的实例,也就是float(12*0.0254)

 

代码3

class inch2(float):
    def __new__(cls, arg=0.0):    # cls 相当于 self
        print(11)
        return float.__new__(cls, arg)*0.0254           # 返回了父类的实例*0.0254
    def __init__(self,aa):
        print(22)               # 这句没有被执行,因为new没有正确返回父类的实例

a = inch2(12)
# 11
print(a)
# 0.3048    =12*0.0254

new没有正确返回父类的实例,导致init没有被执行。