美文网首页
python 中__init__与__new__的区别

python 中__init__与__new__的区别

作者: SevenBy | 来源:发表于2018-02-07 00:00 被阅读282次
    python 中__init__与__new__的区别

    旧式和新式类中的__NEW____INIT__
    本文的目的是讨论Python的__new____init__方法。
    newinit方法不同的行为本身之间以及旧式与新式python类定义之间。

    了解__new____init__之间的区别

    这两种方法的主要区别是__new__处理对象创建,而__init__处理对象初始化。
    在实例化过程中,如果定义不同,这两者在工作方式上略有差异。

    有关Python中的类

    Classes in python are classified as new-style and old-style. Old-style classes are the ones that are prior to python 3 and defined without inheriting from base class 'object', which in turn is inherited from 'type' by default.

    python 2.x中的旧式类:

    class A:  # -> inherits from 'type'
        pass
    

    python 2.x中的新式类:

    class A(object):  # -> clearly inherits from 'object'
        pass
    

    In python 3 there aren't new or old styles of classes and they inherit directly from 'object' so there is no need to specify it as a base anymore.

    在本文的其余部分中,我们将介绍两种情况下的 __new____init__方法,以确定它们的行为方式以及如何使用它们。

    深度讲解

    Before diving into the actual implementations you need to know that new accepts cls as it's first parameter and init accepts self, because when calling new you actually don't have an instance yet, therefore no self exists at that moment, whereas init is called after new and the instance is in place, so you can use self with it.

    __new____init__用于旧式类

    旧式类实际上并没有__new__方法,因为对于它们来说__init__是构造函数,假设如下:

    class A:
        
        def __new__(cls):
            print "A.__new__ is called"  # -> this is never called
    
    A()
    

    在这种情况下new 的主体将永远不会被执行,因为它不是老式类的目的。

    如果我们要重写__init__

    class A:
    
        def __init__(self):
            print "A.__init__ called"
    
    A()
    

    输出将是:

    A.__init__ called
    

    现在让我们尝试从__init__返回一些东西:

    class A:
    
        def __init__(self):
            return 29
    
    A()
    

    这会产生:

    TypeError: __init__() should return None
    

    所以这意味着我们实际上无法控制实例化旧式类时要返回的内容。

    __new____init__用于新的样式类

    新风格的类让开发人员同时覆盖__new____init__,他们有不同的用途,__new__ (构造函数)仅用于创建object__init__ (初始化程序)来初始化它。

    让我们看看他们的执行顺序:

    class A(object):  # -> don't forget the object specified as base
    
        def __new__(cls):
            print "A.__new__ called"
            return super(A, cls).__new__(cls)
    
        def __init__(self):
            print "A.__init__ called"
    
    A()
    

    输出将是:

    A.__new__ called
    A.__init__ called
    

    您可能想知道__init____new__在哪里被调用,而我为您准备的是__new__在调用类名(实例化时)时自动调用,而__init____new__每次由__new__返回时被调用,而将实例返回传递给__init__self'作为参数,因此,即使您将该实例保存在全局/静态的某个位置,并且每次先都从__new__返回,每次都会调用__init__

    知道了这一点就意味着如果我们调用super__new__,那么__init__将不会被执行。让我们来看看是不是这样的情况:

    class A(object):
    
        def __new__(cls):
            print "A.__new__ called"
    
        def __init__(self):
            print "A.__init__ called"  # -> is actually never called
    
    print A()
    

    输出是:

    A.__new__ called
    None
    

    显然,实例被识别为None,因为我们不从构造函数返回任何东西。

    想知道如果我们从__new__返回什么可能会发生什么?

    笑脸

    猜猜输出是什么:

    class A(object):
    
        def __new__(cls):
            print "A.__new__ called"
            return 29
    
    print A()
    

    让我们看看当我们从__init__返回时会发生什么:

    A.__new__ called
    29
    

    这产生:

    class A(object):
    
        def __init__(self):
            print "A.__init__ called" 
                return 33  # -> TypeError: __init__ should return None
    
    A()
    

    这主要是因为调用__init__的处理程序 引发了TypeError异常,并且从__init__返回任何内容都没有意义,因为它的目的只是改变新创建的实例的新状态。


    看起来新型的类在灵活性方面有提高,允许我们在创建和初始化级别执行任何PRE / POST操作,并使我们控制在实例化时返回的内容。
    考虑到这一点,我们试着返回一个不同类的实例。

    首先我们定义一个类:

    class Sample(object):
        
        def __str__(self):
            return "SAMPLE"
    

    然后我们定义__new__覆盖类:

    class A(object):
    
        def __new__(cls):
            return Sample()
    

    这也可以写成:

    class A(object):
    
        def __new__(cls):
            return super(A, cls).__new__(Sample)
    

    然后调用:

    print A()
    

    那会输出:

    SAMPLE
    

    这里是我写的一个例子,帮助大家理解:

    class Alfa(object):
        def __new__(cls):
            #creat a generate ,get int value by filter
            #g=(x for x in range(10) if isinstance(x,int) and x <0)
            print("__new__")
            #return an parent instance 
            return super().__new__(cls)
        def __init__(self):
            print ("__init__")
            print (id(self))#print self address at Memory
            super().__init__()
    #l=['a',1,2,-2,-5,8,9,0]
    t=Alfa()# instantiation a object
    print(id(t))#print self address at Memory
    print(t)
    

    相关文章

      网友评论

          本文标题:python 中__init__与__new__的区别

          本文链接:https://www.haomeiwen.com/subject/ytjnzxtx.html