__new__ 方法是什么?
如果将类比喻为工厂,那么__init__()方法则是该工厂的生产工人,__init__()方法接受的初始化参 数则是生产所需原料,
__init__()方法会按照方法中的语句负责将原料加工成实例以供工厂出货。而 __new__()则是生产部经理,
__new__()方法可以决定是否将原料提供给该生产部工人,同时它还决定着出 货产品是否为该生产部的产品,
因为这名经理可以借该工厂的名义向客户出售完全不是该工厂的产品。
__new__方法是真正的创建实例的,决定了,该类能否创建实例
__new__()方法特性:
1.__new__()方法是在类准备将自身实例化时调用。
2.__new__()方法始终都是类的静态方法,即使没有被加上静态方法装饰器。静态方法只有被类能够调用
一个类可以有多个位置参数和多个关键字参数,而在实例化开始之后,在调用 __init__()方法之前,Python首先调用__new__()方法:
def __new__(cls, *args, **kwargs):
...
如果要得到当前类的实例,应当在当前类中的__new__()方法语句中调用当前类的父类 的__new__()方法
例如,如果当前类是直接继承自object,那当前类的__new__()方法返回的对象应该为:
def __new__(cls, *args, **kwargs):
...
return object.__new__(cls)
(事实上如果(新式)类中没有重写__new__()方法,即在定义新式类时没有重新定义__new__()时 ,
Python默认是调用该类的直接父类的__new__()方法来构造该类的实例,如果该类的父类也没有重写 __new__(),
那么将一直按此规矩追溯至object的__new__()方法,因为object是所有新式类的基类。)
__new__方法接受的参数虽然也是和__init__一样,但__init__是在类实例创建之后调用,而 __new__方法正是创建这个类实例的方法。

当你实例化一个类的时候,具体的执行逻辑是这样的:
p = Person(name, age)
首先使用name和age参数来执行Person类的__new__方法,这个__new__方法会 返回Person类的一个实例
(通常情况下是使用 super(Persion, cls).__new__(cls, ... ...) 这样的方式),
然后利用这个实例来调用类的__init__方法,上一步里面__new__产生的实例也就是 __init__里面的的 self
所以,__init__ 和 __new__ 最主要的区别在于:

__init__ 通常用于初始化一个新实例,控制这个初始化的过程,比如添加一些属性, 做一些额外的操作,发生在类实例被创建完以后。它是实例级别的方法。
__new__ 通常用于控制生成一个新实例的过程。它是类级别的方法。

__new__ 的作用
依照Python官方文档的说法,__new__方法主要是当你继承一些不可变的class时(比如int, str, tuple),
提供给你一个自定义这些类的实例化过程的途径。还有就是实现自定义的metaclass。
在python中,真正创建实例的是__new__方法,这个方法是基于类的层面,__init__是实例创建出来之后,对类进行定制的,基于实例级别的

用__new__来实现单例模式
因为类每一次实例化产生的过程都是通过__new__来控制的,所以通过重载__new__方法,我们 可以很简单的实现单例模式。
===================
__new__() 函数只能用于从object继承的新式类
object将__new__()方法定义为静态方法,并且至少需要传递一个参数cls,cls表示需要实例化的类,此参数在实例化时由Python解释器自动提供
__new__()必须要有返回值,返回实例化出来的实例,需要注意的是,可以return父类__new__()出来的实例,也可以直接将object的__new__()出来的实例返回

===================
例子1
class Demo(object):
def __init__(self):
print '__init__() called...'

def __new__(cls, *args, **kwargs):
print '__new__() - {cls}'.format(cls=cls)
return object.__new__(cls, *args, **kwargs)

if __name__ == '__main__':
de = Demo()

例子2
class Parent(object):
def __new__(cls):
print "Parent __new__ called"
return object.__new__(cls)
class Demo(Parent):
def __init__(self):
print "__init__ called"

def __new__(cls):
print "__new__ called"
return Parent.__new__(cls)

d= Demo()
输出:
__new__ called
Parent __new__ called
__init__ called

__new__方法是一级一级往上回溯走的,从父类最终到祖宗类object,也可以直接调用祖宗类object的__new__方法生成实例
发现实例化对象的时候,调用__init__()初始化之前,先调用了__new__()方法
__new__()必须要有返回值,返回实例化出来的实例,需要注意的是,可以return父类__new__()出来的实例,
也可以直接将object的__new__()出来的实例返回。
__init__()有一个参数self,该self参数就是__new__()返回的实例,__init__()在__new__()的基础上可以完成一些其它初始化的动作,
__init__()不需要返回值。
若__new__()没有正确返回当前类cls的实例,那__init__()将不会被调用,即使是父类的实例也不行。
我们可以将类比作制造商,__new__()方法就是前期的原材料购买环节,__init__()方法就是在有原材料的基础上,加工,初始化商品环节。
(这个类比比较好,new方法完以后,就出来了一个实例,可以认为这个实例还没有任何内容,空的,可以在这个阶段对这个类增加一些新属性,但是仅仅是对类
还不能对类实例操作,__init方法完以后,对这个实例进行了一些修饰,粉饰,这个阶段可以对类和实例,都进行属性的修改增加等操作)
类属性的访问,可以通过类或者实例,但是类属性的修改,只能通过类方式
默认的__new__方法会从子类开始一直调用父类的__new__方法,直到最后调用object的__new__方法。
但每次调用时传入的cls参数都是子类的类对象,所以最终能产生子类对象
===============
__new__()是在新式类中新出现的方法,它作用在构造方法建造实例之前,可以这么理解,在Python 中 存在于类里面的构造方法__init__()负责将类的实例化,
而在__init__()启动之前,__new__()决定是否 要使用该__init__()方法,
因为__new__()可以调用其他类的构造方法或者直接返回别的对象来作为本类 的实例

通常来说,新式类开始实例化时,__new__()方法会返回cls(cls指代当前类)的实例,
然后该类的 __init__()方法作为构造方法会接收这个实例(即self)作为自己的第一个参数,然后依次传入__new__ ()方法中接收的位置参数和命名参数。
注意:如果__new__()没有返回cls(即当前类)的实例,那么当前类的__init__()方法是不会被调用 的。
如果__new__()返回其他类(新式类或经典类均可)的实例,那么只会调用被返回的那个类的构造方 法。
================
在任何新式类的__new__()方法,不能调用自身的__new__()来制造实例,因为这会造成死循环
使用object或者没有血缘关系的新式类的__new__()是安全的,但是如果是在有继承关系的两个类之间,应避免互调造成死循环
===============
因此可以这么描述__new__()和__ini__()的区别,在新式类中__new__()才是真正的实例化方法,为类

提供外壳制造出实例框架,然后调用该框架内的构造方法__init__()使其丰满。
# 如果以建房子做比喻,__new__()方法负责开发地皮,打下地基,并将原料存放在工地。而__init__()
方法负责从工地取材料建造出地皮开发招标书中规定的大楼,__init__()负责大楼的细节设计,建造,装修使其可交付给客户

python new和init知识点的更多相关文章

  1. python类内init外声明的属性与init内声明的对象属性的访问和操作区别

    python类内init外声明的属性与init内声明的对象属性的访问和操作区别(面试题) 1.在ipython中输入以下代码,其输出会是什么? In [1]: class ClassOut: ...: ...

  2. Python OS模块重要知识点

    Python OS模块重要知识点 这几点很重要,主要是关于文件路径,我之前踩了很多坑,今天总结一下,方便以后能够避免与path相关的各种坑! 1,首先我们想获取某个文件夹下面的所有文件夹以及文件(不包 ...

  3. python - 那些零碎的知识点

    python - 那些零碎的知识点 一. 字符串格式化 1. "旧式字符串解析(%操作符)" 'Hello, %s' % name "Hello, Bob" ' ...

  4. Day8 Python基础之遗漏知识点(六)

    1. 遗漏知识点 深.浅拷贝:   http://www.cnblogs.com/yuanchenqi/articles/5782764.html a=b: 浅拷贝: 深拷贝 集合(set) 集合的定 ...

  5. python基础语法及知识点总结

    本文转载于星过无痕的博客http://www.cnblogs.com/linxiangpeng/p/6403991.html 在此表达对原创作者的感激之情,多谢星过无痕的分享!谢谢! Python学习 ...

  6. Python面向对象几个知识点

    一.判断对象是否属于类.判断类是否派生自某个类 class Zero: pass class One(Zero): pass class Two(One, Zero): pass # 判断对象是否完全 ...

  7. Python需要知道的知识点

    1.所有数据类型都自带布尔值,布尔值为假的数据类型 包括( 空字符串,空列表,空字典,空集合).数字(0).None类型 2.Python实现int的时候有个小整数池.为了避免因创建相同的值而重复申请 ...

  8. Python常用基础语法知识点大全

    记得我是数学系的,大二时候因为参加数学建模,学习Python爬虫,去图书馆借了一本Python基础书,不厚,因为有matlab和C语言基础,这本书一个星期看完了,学完后感觉Python入门很快,然后要 ...

  9. Python语言及其应用 - 知识点遍历

    遍历python语法     2.基本元素:数字.字符串和变量 2.1 python有哪些基本类型? 布尔型(True, False),整型(42,100000),浮点型(3.14159,1.0e8) ...

随机推荐

  1. EBS 可拓展的外部信用风险导入

    DECLARE l_msg_count NUMBER; l_msg_data VARCHAR2(2000); l_return_status VARCHAR2(30); l_cc_hold_comme ...

  2. unity 快速创建小地图

    先写一个纹理遮罩shader Shader "Unlit/TexMask" { Properties { _MainTex ("Texture", 2D) =  ...

  3. AngularJS进阶(二十二)实现时间选择插件

    JS实现时间选择插件 引导语 在项目开发过程中,需要实现根据以日期为筛选条件之一,故需要实现时间选择插件.对于未接触的新事物,自己总是感觉不明觉厉.其实,有些实现可以使用很简单的方法即可.以此为例,偶 ...

  4. 【Qt编程】基于Qt的词典开发系列<一>--词典框架设计及成品展示

    去年暑假的时候,作为学习Qt的实战,我写了一个名为<我爱查词典>的词典软件.后来由于导师项目及上课等原因,时间不足,所以该软件的部分功能欠缺,性能有待改善.这学期重新拿出来看时,又有很多东 ...

  5. 【Android 应用开发】Android中使用ViewPager制作广告栏效果 - 解决ViewPager占满全屏页面适配问题

    . 参考界面 : 携程app首页的广告栏, 使用ViewPager实现        自制页面效果图 : 源码下载地址: http://download.csdn.net/detail/han1202 ...

  6. LeetCode之“树”:Balanced Binary Tree

    题目链接 题目要求: Given a binary tree, determine if it is height-balanced. For this problem, a height-balan ...

  7. dos2unix(windows脚本文件放到unix下运行要注意)

    在windows下编写的shell脚本文件,直接放到linux下运行,是不行的. infiniDB的倒库脚本文件load.sh,将tbl文件导入infiniDB,怎么运行不成功,不建job.运来,是w ...

  8. Working with DVT Components

      Introduction to ADF Data Visualization Components - Graphs, Gauge, Maps, Pivot Table and Gantt Pur ...

  9. Java进阶(十六)使用new Date()和System.currentTimeMillis()获取当前时间戳

    java使用new Date()和System.currentTimeMillis()获取当前时间戳 在开发过程中,通常很多人都习惯使用new Date()来获取当前时间,使用起来也比较方便,同时还可 ...

  10. Testbench(转)

    本来还打算自己写下对Testbench的理解,后来发现百度百科名片解释得很好,所以就直接转了. 原文百度百科链接:http://baike.baidu.com/link?url=dxzsOAs32IE ...