• Python中面向对象的__init__,__new__方法剖析


    class A(object):
        def __init__(self,*args, **kwargs):
            print (“123”)
        def __new__(cls,*args, **kwargs):
            print ("456")
            return object.__new__(cls, *args, **kwargs)   
    a = A()
    结果:
    #456  
    #123

      通过类实例化一个对象的时候,"__new__"方法首先被调用,然后是"__init__"方法。

      __init__和__new__总结:

    "__new__"方法在Python中是真正的构造方法(创建并返回实例),通过这个方法可以产生一个"cls"对应的实例对象,所以说"__new__"方法一定要有返回
    对于"__init__"方法,是一个初始化的方法,"self"代表由类产生出来的实例对象,"__init__"将对这个对象进行相应的初始化操作

      第一个参数cls是当前正在实例化的类,如果要得到当前类的实例,应当在当前类中的 "__new__" 方法语句中调用当前类的父类的" __new__" 方法

      但是:

      如果当前类是直接继承自 object,那当前类的 "__new__" 方法返回的对象应该为

    def __new__(cls, *args, **kwargs):
        return object.__new__(cls, *args, **kwargs)
    如果(新式)类中没有重写"__new__"方法,Python默认是调用该类的直接父类的"__new__"方法来构造该类的实例,
    如果该类的父类也没有重写"__new__",那么将一直按照同样的规则追溯至object的"__new__"方法,
    因为object是所有新式类的基类。

    如果新式类中重写了"__new__"方法,那么可以选择任意一个其他的新式类(必须是新式类,只有新式类有"__new__",
    因为所有新式类都是从object派生)的"__new__"方法来创建实例,包括这个新式类的所有前代类和后代类,只要它们不会造成递归死循环。

      init的调用

    "__new__"决定是否要使用该类的"__init__"方法,因为"__new__" 可以调用其他类的构造方法或者直接返回别的类创建的对象来作为本类的实例。
    通常来说,新式类开始实例化时,"__new__"方法会返回cls(cls指代当前类)的实例,然后调用该类的"__init__"方法作为初始化方法,
    该方法接收这个实例(即self)作为自己的第一个参数,然后依次传入"__new__"方法中接收的位置参数和命名参数。
    但是,如果
    "__new__"没有返回cls(即当前类)的实例,那么当前类的"__init__"方法是不会被调用的。

      示例:

    class A(object):
        def __init__(self, *args, **kwargs):
            print "123“
        
        def __new__(cls, *args, **kwargs):
            obj = object.__new__(cls, *args, **kwargs)
            print "456”
            return obj   
    
    class B(object):
        def __init__(self, *args, **kwargs):
            print "789“
        
        def __new__(cls, *args, **kwargs):
            obj = object.__new__(A, *args, **kwargs)
            print "xxx"
            return obj      
    
    b = B()
    print type(b)
  • 相关阅读:
    Codeforces Round #609 (Div. 1)
    Codeforces Round #607 (Div. 1)
    Codeforces Round #604 (Div. 1)
    网络流应用
    javaScript遍历数组总结
    JavaScript遍历对象的常见方法
    JS中的可枚举属性与不可枚举属性
    typeScript泛型
    ts中函数重载声明
    ts中的可选参数
  • 原文地址:https://www.cnblogs.com/sxh-myblogs/p/8260756.html
Copyright © 2020-2023  润新知