概述

  __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. Spring Bean装配(上)

    Bean:在spring的IOC里面,把配置到IOC容器里面的实体或者是对象都称为Bean Bean配置项 Bean的作用域 Bean的生命周期 Bean的自动装配 Resources&Res ...

  2. python自动华 (十六)

    Python自动化 [第十六篇]:JavaScript作用域和Dom收尾 本节内容: javascript作用域 DOM收尾 JavaScript作用域 JavaScript的作用域一直以来是前端开发 ...

  3. 给json数组添加新字段并赋值

    zNodes.forEach(function(item) { item.newtitle ="点击加号设为主席会场"; });

  4. learning armbian steps(5) ----- armbian 构建arm rootfs

    基于learning armbian step(4) 的总结,我们来实践一下,接下来的会把整个构建的log都贴出来: vmuser@vmuser-virtual-machine:~/qemu-arm$ ...

  5. 【线性代数】6-6:相似矩阵(Similar Matrices)

    title: [线性代数]6-6:相似矩阵(Similar Matrices) categories: Mathematic Linear Algebra keywords: Similar Matr ...

  6. 转:关于C++ const 的全面总结

    转自:https://www.cnblogs.com/xkfz007/articles/2419518.html    如有侵权请联系博主,立即删除. C++中的const关键字的用法非常灵活,而使用 ...

  7. c++ 使用类生成随机数

    // generate algorithm example #include <iostream> // cout #include <algorithm> // genera ...

  8. ImportError: No module named rospy

    Traceback (most recent call last): File "manage.py", line 4, in <module> import rosp ...

  9. Matlab下imwrite,Uint16的深度图像

    Matlab下imwrite,Uint16的深度图像 1. 在Matlab命令窗口输入命令: help imwrite 会有如下解释: If the input array is of class u ...

  10. Reids入门介绍

    一.入门概述 1.是什么? Redis:REmote DIctionary Server(远程字典服务器) 是完全开源免费的,用C语言编写的,遵守BSD协议,是一个高性能的(key/value)分布式 ...