34 Python __new__与__init__区别

__new__() 是新式类中新出现的类方法,它在构造方法(__init__())之前调用。

__new__()的声明

def __new__(cls, *args, **kwargs):
    pass

__new__()的参数和__init__()一样,但__init__()是在类实例创建之后调用,而 __new__()方法正是创建类实例的方法。__init__()有一个参数self,self就是__new__()返回的实例,__init__()__new__()的基础上完成一些其它初始化的动作,__init__()不需要返回值。

class Foo(object):
    def __init__(self):
        print '__init__'

    def __new__(cls,*args,**kargs):
        print '__new__'
        return super(Foo,cls).__new__(cls,*args,**kargs)
f = Foo()
'''
__new__
__init__
'''

上述代码可证明__new__()方法的调用在__init__()之前。

执行过程如下

  1. f = Foo()
  2. 执行Foo的__new__()方法,__new__()方法返回Foo的一个实例
  3. 执行__new__()方法返回实例的__init__()方法

由以上可知,__init__()__new__()的区别主要有以下

  1. __init__() 通常用于初始化一个新实例,控制实例的初始化过程,比如添加一些属性, 做一些额外的操作,发生在类实例被创建完以后,它是实例级别的方法

  2. __new__() 通常用于控制生成一个新实例,它是类级别的方法

以建房子做比喻,__new__()方法负责开发地皮,打下地基,并将原料存放在工地;

__init__()方法负责从工地取材料建造出地皮开发招标书中规定的大楼;

大楼的细节设计,装修交给客户完成(也就是实例的使用者)。

可利用__new__()实现单例模式

#!/usr/bin/python
# -*- coding: utf-8 -*-
class Singleton(object):
    '''单例模式'''
    def __init__(self):
        print '__init__'

    def __new__(cls,*args,**kargs):
        if not cls.__dict__.get('_Singleton__instance'):
            cls._Singleton__instance = super(Singleton,cls).__new__(cls,*args,**kargs)
        return cls._Singleton__instance

m = Singleton()
n = Singleton()
print m is n
'''
__init__
__init__
True
'''

__new__() 的特性

  1. __new__() 方法在类准备将自身实例化时调用;
  2. __new__() 方法始终都是类的静态方法,即使没有被加上静态方法装饰器;

注意

  1. 如果在定义新式类时没有重定义__new__(),Python默认按照MRO顺序调用其父类的__new__()方法来构造该类的实例,因为object是所有新式类的基类,所以一定能找到__new__()方法;

  2. 如果新式类重写了__new__()方法,那么可以任意选择一个新式类的__new__()方法来制造实例;

    (一定要是新式类,新式类必有__new__(),因为所有新式类都是object的后代,而经典类则没有__new__()方法)

  3. 如果__new__()没有返回当前类的实例,那么当前类的__init__()方法是不会被调用的;

    如果__new__()返回其他类(新式类或经典类均可)的实例,那么会调用被返回的那个类的构造方法;

    也就是说返回谁的实例,就调用谁的__init__()方法,不返回实例,不会调用__init__()方法

    class Foo1(object):
       def __init__(self, *args, **kwargs):
           print "Foo1 __init__"
    
       def __new__(cls, *args, **kwargs):
           return super(Foo1,cls).__new__(cls, *args, **kwargs)  
    
    class Foo2(object):
       def __init__(self):
           print "Foo2 __init__"
    
       def __new__(cls, *args, **kwargs):
        '''返回Foo1的实例'''
        return Foo1()
    
    class Foo3(object):
       def __init__(self):
           print "Foo3 __init__"
    
       def __new__(cls, *args, **kwargs):
        pass
    
    foo1 = Foo1()      #Foo1 __init__
    print type(foo1)   #<class '__main__.Foo1'>
    
    foo2 = Foo2()      #Foo1 __init__,调用的是Foo1的__init__()方法
    print type(foo2)   #<class '__main__.Foo1'>
    
    foo3 = Foo3()
    print type(foo3)   #<type 'NoneType'>

转载请标明出处,原文地址(http://blog.csdn.net/lis_12/article/details/54631089).

如果觉得本文对您有帮助,请点击‘顶’支持一下,您的支持是我写作最大的动力,谢谢。

参考网址

  1. http://www.cnblogs.com/ifantastic/p/3175735.html
  2. http://python.jobbole.com/86506/
  3. http://stackoverflow.com/questions/674304/pythons-use-of-new-and-init
  4. http://blog.csdn.net/lis_12/article/details/52859376
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值