• 第8.8节 Python使用__new__方法和构造方法__init__完成类实例化的过程详解


    第8.8节 Python使用__new__方法和构造方法__init__完成类实例化的过程详解

    前面章节介绍了Python类中的__new__方法和构造方法__init__,并通过实例分析了二者之间关系,本节系统化的总结一下Python中类实例化过程。具体步骤如下:
    一、 开发者通过对象构造器表达式“实例对象=类(参数列表)”启动创建新的实例的任务;
    二、 Python查找类的__new__方法
    Python首先在准备实例化的类中找new__方法,如果对应类没有__new__方法则从直接父类中查找,如果从直接父类中查找也没有,再找直接父类的直接父类,依此类推,一直到查到一个__new__方法为止(如果自定义类没有,则会找到所有类的父类object类的__new__方法)。
    三、 Python传递参数给类的__new__方法
    Python找到类对应的__ new__方法后,将对象构造器表达式中的类以及参数列表传给查找到的__new__方法(如果是object类的__new__方法,是否只传自定义类的类名还是参数都传参老猿尚未确认)作为参数,并执行该方法的代码;

    1. __new__方法在应用通过对象构造器表达式触发时至少要有一个参数cls,代表要实例化的类对象,此参数在实例化时由Python解释器自动提供;
    2. 常规情况下,__new__方法执行时,除了object类的__new__方法,所有类中重写的__new__方法都必须调用其父类的__new__方法,并在调用时将本方法中的第一个实参cls传给父类的__new__方法作为第一个参数;
    3. 自定义类的__new__方法调用传入的cls,除了逐层传入外,也可以进行调整,在某些情况下,根据应用需要可以将cls参数对应实参修改为其他类;
    4. 在上述调用层级中,object类的__new__方法一定是最后调用的一个;
    5. 每个自定义类的__new__()方法不能在该方法内调用自身的__new__()来制造实例,必须调用父类的方法,否则会造成死循环。
      四、 __new__方法返回实例对象
      object类的__new__最先返回一个参数cls对应的实例给调用其的自定义子类,自定义子类__new__方法根据情况继续返回给其调用子类的__new__方法,直到返回给对象构造器表达式的调用方。
      所有父类执行__new__方法后必须向子类返回一个实例对象,该实例对象常规情况下是__new__方法第一个参数cls对应的“类”实例,子类再将该实例返回给其调用者,直到传递回给最开始的调用者即“对象构造器表达式”对应的应用;
    6. 由于自定义类的__new__方法调用传入的cls可以修改,上层自定义类的__new__方法也可以改变返回值的值和类型,因此有可能返回的实例不一定是“对象构造器表达式”对应的“类”;
    7. 使用__new__()方法改变返回的实例类型主要是为了允许不可变类型(如int, str, tuple)的子类定制实例,还有就是实现自定义的metaclass。关于metaclass(元类)的内容老猿还没深入研究,暂不介绍。

    五、 Python判断__new__方法返回实例对象是否是对象构造器表达式中”类”cls的实例,如果不是则不会调用任何类的构造方法(即使是父类的实例也不行),直接将实例返回给对象构造器表达式的调用方,否则转下步;

    1. 关于这点,老猿验证了几种情况是都不会执行任何类的构造方法,但在网上一些资料查阅的情况,有说可以执行返回实例对应类的构造方法的,老猿没有碰到这种情况,但也许真有这种情况,或许需要特定条件才会触发,因此将这个疑点在此记录下来。
      六、 __new__方法执行完成后,如果返回的实例是cls类的实例,则将此实例作为self传递给构造方法,并将__new__方法中除cls外的参数也传给构造方法;
      七、 执行构造方法,构造方法执行后将实例返回给在对象构造器表达式左侧的”实例对象”,完成整个类的实例化过程。

    老猿Python系列文章用于逐步介绍老猿学习Python后总结的学习经验,这些经验有助于没有接触过Python的程序员可以很容易地进入Python的世界。
    欢迎大家批评指正,谢谢大家关注!

  • 相关阅读:
    pycharm中将文件目录标记为sources root和sys.path.append()效果一样
    简单的股票信息查询系统 1 程序启动后,给用户提供查询接口,允许用户重复查股票行情信息(用到循环) 2 允许用户通过模糊查询股票名,比如输入“啤酒”, 就把所有股票名称中包含“啤酒”的信息打印出来 3 允许按股票价格、涨跌幅、换手率这几列来筛选信息, 比如输入“价格>50”则把价格大于50的股票都打印,输入“市盈率<50“,则把市盈率小于50的股票都打印,不用判断等于。
    添加jar到本地maven库
    jquery.qrcode中文乱码的解决终极办法
    easyUI datagrid view扩展
    CANNOT READ PROPERTY ‘opera’ OF UNDEFINED解决方法
    关于 Promise 的一些简单理解
    Java 内功修炼 之 数据结构与算法(一)
    学习一下 JVM (三) -- 了解一下 垃圾回收
    学习一下 JVM (二) -- 学习一下 JVM 中对象、String 相关知识
  • 原文地址:https://www.cnblogs.com/LaoYuanPython/p/11087676.html
Copyright © 2020-2023  润新知