zoukankan      html  css  js  c++  java
  • ___new__方法和__init__方法的区别

    复制代码
    1 class A(object):
    2     def __init__(self,*args, **kwargs):
    3         print "init A"
    4     def __new__(cls,*args, **kwargs):
    5         print "new A %s"%cls
    6      #return super(A, cls).__new__(cls, *args, **kwargs)
    7         return object.__new__(cls, *args, **kwargs)
    复制代码

    说明

    1、继承自object的新式类才有__new__

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

    3、__new__必须要有返回值,返回实例化出来的实例,这点在自己实现__new__时要特别注意,可以return父类(通过super(当前类名, cls))__new__出来的实例,或者直接是object的__new__出来的实例

    4、__init__有一个参数self,就是这个__new__返回的实例,__init__在__new__的基础上可以完成一些其它初始化的动作,__init__不需要返回值

    5、如果__new__创建的是当前类的实例,会自动调用__init__函数,通过return语句里面调用的__new__函数的第一个参数是cls来保证是当前类实例,如果是其他类的类名,;那么实际创建返回的就是其他类的实例,其实就不会调用当前类的__init__函数,也不会调用其他类的__init__函数。

    在继承派生时的调用顺序

    复制代码
    1 class B(A):
    2     def __init__(self,*args, **kwargs):
    3         print "init B"
    4     def __new__(cls,*args, **kwargs):
    5         print "new B %s"%cls
    6      #return super(B, cls).__new__(cls, *args, **kwargs)
    7         return object.__new__(cls, *args, **kwargs)
    复制代码

    1、在定义子类时没有重新定义__new__()时,Python默认是调用该类的直接父类的__new__()方法来构造该类的实例,如果该类的父类也没有重写__new__(),那么将一直按此规矩追溯至object的__new__()方法,因为object是所有新式类的基类。

    2、而如果子类中重写了__new__()方法,那么你可以自由选择任意一个的其他的新式类(必定要是新式类,只有新式类必定都有__new__(),因为所有新式类都是object的后代,而经典类则没有__new__()方法)的__new__()方法来制造实例,包括这个新式类的所有前代类和后代类,只要它们不会造成递归死循环。反正肯定不能调用自己的__new__,这肯定是死循环。

    3、对于子类的__init__,其调用规则跟__new__是一致的,当然如果子类和父类的__init__函数都想调用,可以在子类的__init__函数中加入对父类__init__函数的调用。

    4、我们在使用时,尽量使用__init__函数,不要去自定义__new__函数,因为这两者在继承派生时的特性还是很不一样的。

    __new__ 的作用

    1、__new__方法主要是当你继承一些不可变的class时(比如int, str, tuple), 提供给你一个自定义这些类的实例化过程的途径。

    假如我们需要一个永远都是正数的整数类型,通过集成int,我们可能会写出这样的代码。

    复制代码
    1 class PositiveInteger(int):
    2     def __init__(self, value):
    3         super(PositiveInteger, self).__init__(self, abs(value))
    4 
    5 
    6 i = PositiveInteger(-3)
    7 print i
    复制代码

    但运行后会发现,结果根本不是我们想的那样,我们任然得到了-3。这是因为对于int这种 不可变的对象,我们只有重载它的__new__方法才能起到自定义的作用。
    这是修改后的代码:

    复制代码
    class PositiveInteger(int):
        def __new__(cls, value):
            return super(PositiveInteger, cls).__new__(cls, abs(value))
    
    
    i = PositiveInteger(-3)
    print i
    复制代码

    通过重载__new__方法,我们实现了需要的功能。

    2、实现单例

    事实上,当我们理解了__new__方法后,我们还可以利用它来做一些其他有趣的事情,比如实现 设计模式中的 单例模式(singleton) 。
    因为类每一次实例化后产生的过程都是通过__new__来控制的,所以通过重载__new__方法,我们 可以很简单的实现单例模式。

    复制代码
    class Singleton(object):
        def __new__(cls):
            # 关键在于这,每一次实例化的时候,我们都只会返回这同一个instance对象
            if not hasattr(cls, 'instance'):
                cls.instance = super(Singleton, cls).__new__(cls)
            return cls.instance
    
    
    obj1 = Singleton()
    obj2 = Singleton()
    
    
    obj1.attr1 = 'value1'
    print obj1.attr1, obj2.attr1
    print obj1 is obj2
    复制代码

    输出结果:
    value1 value1
    True
    可以看到obj1和obj2是同一个实例。

    复制代码
    class Singleton(object):
        __instance = None
    
    
        def __init__(self, *args, **kwargs):
            pass
    
    
        def __new__(cls, *args, **kwargs):
            if not cls.__instance:
                # if not hasattr(cls, 'instance'):
                cls.__instance = super(Singleton, cls).__new__(cls, *args, **kwargs)
                cls.__instance.aa = args[0]
                print type(cls), type(cls.__instance), type(cls.__instance.aa)
            return cls.__instance
    
    obj1 = Singleton(1, 2, 3, b=2)
    obj2 = Singleton(1, 2, 3, b=2)
    
    obj1.attr1 = 'value1'
    obj2.attr2 = 'value2'
    print obj1.attr1, obj1.attr2
    print obj1 is obj2
    print obj1.aa, obj2.attr1 
    复制代码

    结果:
    <type 'type'> <class '__main__.Singleton'> <type 'int'>
    value1 value2
    True
    1 value1

    3、实现自定义的metaclass。

    参考链接:

    http://www.cnblogs.com/ifantastic/p/3175735.html

    https://my.oschina.net/leejun2005/blog/207371

  • 相关阅读:
    分层图最短路(DP思想) BZOJ2662 [BeiJing wc2012]冻结
    动态规划 BZOJ1925 地精部落
    线性DP SPOJ Mobile Service
    线性DP codevs2185 最长公共上升子序列
    数位DP POJ3208 Apocalypse Someday
    线性DP POJ3666 Making the Grade
    杨氏矩阵 线性DP? POJ2279 Mr.Young's Picture Permutations
    tarjan强连通分量 洛谷P1262 间谍网络
    树链剖分 BZOJ3589 动态树
    二分图 BZOJ4554 [Tjoi2016&Heoi2016]游戏
  • 原文地址:https://www.cnblogs.com/cmd61/p/11272834.html
Copyright © 2011-2022 走看看