第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的世界。

欢迎大家批评指正,谢谢大家关注!

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

  1. 第8.5节 Python类中的__new__方法和构造方法__init__关系深入剖析:执行顺序及参数关系案例详解

    上节介绍了__new__()方法这个比构造方法还重要的方法的语法,本节通过案例来详细剖析__new__()方法的细节以及它与构造方法之间的关系. 一.    案例说明 本节以圆Cir类为例来说明,为了 ...

  2. [Python] Python 之 __new__() 方法与实例化

    __new__() 是在新式类中新出现的方法,它作用在构造方法建造实例之前,可以这么理解,在 Python 中存在于类里面的构造方法 __init__() 负责将类的实例化,而在 __init__() ...

  3. Python 之 __new__() 方法与实例化

    原文链接:https://www.cnblogs.com/ifantastic/p/3175735.html __new__() 是在新式类中新出现的方法,它作用在构造方法建造实例之前,可以这么理解, ...

  4. Python 之 __new__() 方法与实例化(转)

    _new__() 是在新式类中新出现的方法,它作用在构造方法建造实例之前,可以这么理解,在 Python 中存在于类里面的构造方法 __init__() 负责将类的实例化,而在 __init__() ...

  5. python的__new__方法

    https://www.cnblogs.com/kex1n/p/5991249.html https://blog.csdn.net/wwx890208/article/details/8053445 ...

  6. 【python】Python 之 __new__() 方法与实例化

    本文转自:http://www.cnblogs.com/ifantastic/p/3175735.html __new__() 是在新式类中新出现的方法,它作用在构造方法建造实例之前,可以这么理解,在 ...

  7. Python 的 __new__()方法与实例化

    __new__() 是新式类中才有的方法,它执行在构造方法创建实例之前.可以这么理解,在 Python 中类中的构造方法 __init__() 负责将类实例化,而在 __init__() 启动之前,_ ...

  8. [Python]python面向对象 __new__方法及单例设计

    __new__ 方法 使用 类名() 创建对象时,Python 的解释器 首先 会 调用 __new__ 方法为对象 分配空间 __new__ 是一个 由 object 基类提供的 内置的静态方法,主 ...

  9. Python中__new__方法为什么有人说是构造方法?有什么作用?

    __new__方法是Python新式类引入的,通常用于控制生成一个新实例的过程.它是类级别的静态方法,是在创建实例对象前执行,如果自定义类中没有重写该方法,则Python自动调用父类的方法,当所有父类 ...

随机推荐

  1. 凯撒密码(Java)

    事实上就是把每个字母偏移一下而已,并且字符不限于a-zA-z,可以是别的,那就很显而易见了,代码如下:定义一个Caesar密码类,成员变量只有密钥,也就是偏移量key 代码如下: public cla ...

  2. c#分割

    Hashtable h = new Hashtable(); ArrayList l = new ArrayList(); string[] lines = System.IO.File.ReadAl ...

  3. EVM 2.0 预览版,跃见非凡,源于鸿蒙,开启物联网小程序新时代

    1. 基于EVUE的物联网小程序 EVM诞生以来,一直致力于让物联网开发变得简单,自鸿蒙OS 1.0 发布后,最引人注目的莫过于华为在应用程序开发框架层面面向应用开发者提供了一种全新的开发方式: 框架 ...

  4. Linux下端口被占用,关掉端口占用的方法

    Linux下端口被占用(例如端口3000),关掉端口占用的进程的方法: 1.netstat -tln | grep 3000 2.sudo lsof -i:3000 3.sudo kill -9 进程

  5. binary hacks读数笔记(objdump命令)

    一.首先看一下几个常用参数的基本含义: objdump命令是Linux下的反汇编目标文件或者可执行文件的命令,它还有其他作用,下面以ELF格式可执行文件test为例详细介绍: 1.objdump -f ...

  6. prop()和attr()我该翻谁的牌子?

    先上代码: // 全选 function CheckAll() { if ($("#th_checkbox").prop('checked')) $('input[name=&qu ...

  7. Docker与Ceph的分与合

    前言 docker是一个管理工具,在操作系统之上提供了一个新的独立轻环境,好处是本地提供了一个基础镜像,然后基于镜像再运行环境,也可以把环境重新打包为镜像,管理起来类似于git,感觉非常的方便,并且能 ...

  8. Leetcode 1329. 将矩阵按对角线排序 题解

    首先遍历对角线元素,顺序为: 先从第一列的最后一行到第一行 然后从第一行的第一列到最后一列 遍历的同时记录坐标和数值,对数值进行排序,然后坐标顺序放回. class Solution: def dia ...

  9. 讲武德,你们要的高性能日志工具 Log4j2,来了

    Log4j 介绍过了,SLF4J 介绍过了,Logback 也介绍过了,你以为日志系列的文章就到此终结了? 不不不,我告诉你,还有一个 Log4j 2,顾名思义,它就是 Log4j 的升级版,就好像手 ...

  10. Linux提权(持续更新)

    利用/etc/passwd提权 个人认为,这种提权方式在现实场景中难以实现,条件太过苛刻,但是建立Linux下的隐藏账户是个不错的选择,灵感来自:https://www.hackingarticles ...