概述

  __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. 解决python中调用 imread 报错:ImportError: cannot import name imread

    安装了scipy后,报cannot import name imread错误, 1.网上查阅资料后说是需要安装pillow,安装pillow之后,仍然报该错误, 2.网上说是pillow与SciPy安 ...

  2. spring-AOP动态代理,以及aspectJ的xml配置或注解配置方法,各个拦截器的使用顺序

    package com.itheima.aspect; public class MyAspect { public void check_Permissions(){ System.out.prin ...

  3. 使用@ConfigurationProperties注解 提示 “Spring Boot Configuration Annotation Processor not found in classpath ”

    解决方案: 在 pom.xml 添加依赖 <dependency> <groupId>org.springframework.boot</groupId> < ...

  4. jface viewer 全选

    viewer.setSelection(new StructuredSelection(((List)viewer.getInput()))); StructuredSelection有多个构造方法, ...

  5. 在 Linux 下使用 scp 命令

    将文件或文件夹从网络上的一个主机拷贝到另一个主机当中去. here:在 Linux 下使用 scp 命令 摘要: scp 是安全拷贝协议(Secure Copy Protocol)的缩写, scp 是 ...

  6. PHP mysqli_errno() 函数

    返回最近调用函数的最后一个错误代码: <?php // 假定数据库用户名:root,密码:123456,数据库:RUNOOB $con=mysqli_connect("localhos ...

  7. 013_Linux驱动之_poll机制

    1. 功能:poll的机制与select相似,与select在本质上没有多大差别.管理多个描写叙述符也是进行轮询,依据描写叙述符的状态进行处理,可是poll没有最大文件描写叙述符数量的限制. 2. 技 ...

  8. 参数类型 (@Service层) interface 常用参数类型举例

    public AdvMessage getMessage(String message, String type); public List<Map<String,Object>&g ...

  9. PHP基础--traits的应用

    Traits 在PHP中实现在方法的重复使用:Traits与Class相似,但是它能够在Class中使用自己的方法而不用继承: Traits在Class中优先于原Class中的方法,引用PHP Doc ...

  10. LibreOJ #113. 最大异或和

    二次联通门 : LibreOJ #113. 最大异或和 /* LibreOJ #113. 最大异或和 线性基 插入 与 查询最大值 说一下我在学习线性基时遇到的一些问题 1.线性基指的是一个数集 2. ...