概述

  __new__() 是在新式类中新出现的方法,在 Python 中类实例化时,__new__()方法用在 __init__() 启动之前,决定是否要使用该 __init__() 方法,因为__new__() 可以调用其他类的构造方法或者直接返回别的对象来作为本类的实例。
特性总结:

  1. __new__()方法是类在准备实例化时调用,也就是实例化之前。
  2. __new__()方法始终都是类的静态方法,即使没有加上静态方法装饰器。

示例1:

def __new__(cls,*args,**kwargs):
...
return object.__new__(cls)

注意:

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

强化进阶

  网上有个很赞的比喻:如果将类比喻为工厂,那么__init__()方法则是该工厂的生产工人,__init__()方法接受的初始化参数则是生产所需原料,__init__()方法会按照方法中的语句负责将原料加工成实例以供工厂出货。而__new__()则是生产部经理,__new__()方法可以决定是否将原料提供给该生产部工人,同时它还决定着出货产品是否为该生产部的产品,因为这名经理可以借该工厂的名义向客户出售完全不是该工厂的产品。

示例2:

 #!/usr/bin/env python
#-*- coding:utf-8 -*- class A(object):
static_var = "withClass" def __init__(self):
self.hostname = "MySql"
self.user = "root" def mod_user(self,name):
self.user = name def putongMethed(self):
print "普通方法:putongMethod" @property
def property_var(self):
return "property_var" @staticmethod
def static_method():
print "静态方法:StaticMethod" @classmethod
def class_method(cls):
print "类方法:ClassMethod" class B(A):
def __new__(cls, *args, **kwargs):
print "实例化前的类对象:%s"%cls
print "实例化前的类参数:%s"%cls.__dict__
#在这里,B为A的派生类,A为B的基类,调用基类A的__new__()方法,并指向A的__init__()构造函数。
return A.__new__(A,*args,**kwargs) if __name__=="__main__":
obj = B()
print "类对象的静态字段:%s"%B.static_var
B.static_method()
B.class_method()
print "类属性:%s" % obj.property_var
print "实例对象: %s"%obj
obj.putongMethed()
print "实例对象的参数:%s"%obj.__dict__
#__new__()仅指定实例构造方法__init__(),并不执行该方法初始化实例
obj.__init__()
print "执行__init__()初始化的参数:%s"%obj.__dict__
#调用A类中的方法
obj.mod_user("mysql")
print "调用A类方法修改普通字段: %s"%obj.__dict__

狸猫换太子

结果:

类对象:<class '__main__.B'>
实例化前的类参数:{'__module__': '__main__', '__new__': <staticmethod object at 0x022E7230>, '__doc__': None}
类对象的静态字段:withClass
静态方法:StaticMethod
类方法:ClassMethod
类属性:property_var
实例对象: <__main__.A object at 0x022E72D0>
普通方法:putongMethod
实例对象的参数:{}
执行__init__()初始化的参数:{'hostname': 'MySql', 'user': 'root'}
调用A类方法修改普通字段: {'hostname': 'MySql', 'user': 'mysql'}

示例解读:

  1. 经理(__new__())借该工厂(B)的名义向客户(obj)出售完全不是该工厂的产品(A的__init__()以及A类指针)。
  2. 我们可以看到A类的静态字段,静态方法,类方法都被B类完美继承,可以通过B.xxMethod获得。
  3. obj=B()实例化时,得到的实例对象的指针却指向了A类,这就是__new__()狸猫换太子,借B工厂将他的父类A给打包出售了。
  4. 因为obj的类指针指向了A,所以可以调用A的普通方法,这是如果调用B类中的普通方法或静态字段时,就会报错!!
  5. obj.__dict__()查看实例对象中的参数,发现为空,没错,这里__new__()只是给了个地址(A和A.__init__()的地址),初始化需要手动执行。
  6. 收到执行obj.__init__()函数后,读取实例对象参数,就得到了A类下的__init__()的数据结构。

类实例化过程

实例对象(独有的命名空间)= 指向类对象的指针 + 普通字段

新式类__new__()方法的更多相关文章

  1. 第8.7节 Python类__new__方法和构造方法关系深入剖析:__new__方法执行结果对__init__的影响案例详解

    一. 引言 前面章节介绍了类中的构造方法和__new__方法,并分析了二者执行的先后顺序关系.__new__方法在__init__方法前执行,__new__方法执行后才返回实例对象,也就是说__new ...

  2. p3新式类__new__使用和实例化

    嗯,new方法返回的是一个全新的对象是真正在内存中分配的内存地址 示例1·class Foo(object): # __metaclass__ = MyType def __init__(self, ...

  3. 类 __new__方法实现单例

    继承了单例的类,子类也是单例模式

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

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

  5. 新式类 VS 经典类

    一.概述 Python中支持多继承,也就是一个子类可以继承多个父类/基类.当一个调用一个自身没有定义的属性时,它是按照何种顺序去父类中寻找的呢?尤其是当众多父类中都包含有同名的属性,这就涉及到新式类 ...

  6. python之新式类与经典类

    经典类与新式类 经典类:P 或 P()--深度查找,向上查父节点 新式类 :P(object)---广度查找,继承object,新式类的方法较多  

  7. python中的__new__与__init__,新式类和经典类(2.x)

    在python2.x中,从object继承得来的类称为新式类(如class A(object))不从object继承得来的类称为经典类(如class A()) 新式类跟经典类的差别主要是以下几点: 1 ...

  8. python开发学习-day07(面向对象之多态、类的方法、反射、新式类and旧式类、socket编程)

    s12-20160227-day07 *:first-child { margin-top: 0 !important; } body>*:last-child { margin-bottom: ...

  9. python2中的__new__与__init__,新式类和经典类-乾颐堂

    在python2.x中,从object继承得来的类称为新式类(如class A(object))不从object继承得来的类称为经典类(如class A()) 新式类跟经典类的差别主要是以下几点: 1 ...

随机推荐

  1. PHP程序员的技术成长规划(转载)

    按照了解的很多PHP/LNMP程序员的发展轨迹,结合个人经验体会,抽象出很多程序员对未来的迷漫,特别对技术学习的盲目和慌乱,简单梳理了这个每个阶段PHP程序员的技术要求,来帮助很多PHP程序做对照设定 ...

  2. java8之Metaspace

         HotSpot JVM是java中最常用的java虚拟机.在java8 HotSpot JVM 中,虚拟机的内存模型做了修改调整.以前HotSpot JVM的内存模型分为新生代,老年代,永久 ...

  3. Nginx中ngx_stream_core_module和ngx_stream_proxy_module

    ngx_stream_core_module模块该模块模拟基于tcp或udp的服务连接的反向代理理,即⼯工作于传输层的调度器器指令:17.1 streamSyntax: stream { ... }D ...

  4. github下载慢的问题

    1. 修改HOSTS文件:在“C:\Windows\System32\drivers\etc” 下的HOSTS文件,添加以下地址:  151.101.44.249 github.global.ssl. ...

  5. 关于pageHelper无法查到总数踩到的坑

    问题代码 PageHelper.startPage(pageNum,pageSize); List<pojoVo> pojoVo=robotService.getPageList(); P ...

  6. 【题解】P3069 [USACO13JAN]牛的阵容Cow Lineup-C++

    题目传送门 思路这道题目可以通过尺取法来完成 (我才不管什么必须用队列)什么是尺取法呢?顾名思义,像尺子一样取一段,借用挑战书上面的话说,尺取法通常是对数组保存一对下标,即所选取的区间的左右端点,然后 ...

  7. ueditor批量上传word图片

    图片的复制无非有两种方法,一种是图片直接上传到服务器,另外一种转换成二进制流的base64码目前限chrome浏览器使用首先以um-editor的二进制流保存为例:打开umeditor.js,找到UM ...

  8. [Poj] Roads in the North

    http://poj.org/problem?id=2631 树的直径裸题 dfs/bfs均可 /* dfs */ #include <iostream> #include <cst ...

  9. 自制 yum 源仓库

    转自:https://www.cnblogs.com/marility/p/7278374.html 背景 客户服务器为内网机器,centos7系统,且无法与外网连接.需要部署对应的LANMP环境及其 ...

  10. 集合家族——stack

    一.概述 在 Java 中 Stack 类表示后进先出(LIFO)的对象堆栈.栈是一种非常常见的数据结构,它采用典型的先进后出的操作方式完成的 它通过五个操作对类 Vector 进行了扩展 ,允许将向 ...