Python中__new__与__init__方法的区别详解


Posted in Python onMay 04, 2015

在python2.x中,从object继承得来的类称为新式类(如class A(object))不从object继承得来的类称为经典类(如class A())

新式类跟经典类的差别主要是以下几点:

1. 新式类对象可以直接通过__class__属性获取自身类型:type

2. 继承搜索的顺序发生了改变,经典类多继承时属性搜索顺序: 先深入继承树左侧,再返回,开始找右侧(即深度优先搜索);新式类多继承属性搜索顺序: 先水平搜索,然后再向上移动

例子:

经典类: 搜索顺序是(D,B,A,C)

>>> class A: attr = 1
...
>>> class B(A): pass
...
>>> class C(A): attr = 2
...
>>> class D(B,C): pass
...
>>> x = D()
>>> x.attr
1

新式类继承搜索程序是宽度优先

新式类:搜索顺序是(D,B,C,A)

>>> class A(object): attr = 1
...
>>> class B(A): pass
...
>>> class C(A): attr = 2
...
>>> class D(B,C): pass
...
>>> x = D()
>>> x.attr
2

3. 新式类增加了__slots__内置属性, 可以把实例属性的种类锁定到__slots__规定的范围之中。

4. 新式类增加了__getattribute__方法

5.新式类内置有__new__方法而经典类没有__new__方法而只有__init__方法

注意:Python 2.x中默认都是经典类,只有显式继承了object才是新式类

   而Python 3.x中默认都是新式类(也即object类默认是所有类的祖先),不必显式的继承object(可以按照经典类的定义方式写一个经典类并分别在python2.x和3.x版本中使用dir函数检验下。

例如:

class A():



pass


  print(dir(A))

会发现在2.x下没有__new__方法而3.x下有。

接下来说下__new__方法和__init__的区别:

在python中创建类的一个实例时,如果该类具有__new__方法,会先调用__new__方法,__new__方法接受当前正在实例化的类作为第一个参数(这个参数的类型是type,这个类型在c和python的交互编程中具有重要的角色,感兴趣的可以搜下相关的资料),其返回值是本次创建产生的实例,也就是我们熟知的__init__方法中的第一个参数self。那么就会有一个问题,这个实例怎么得到?

注意到有__new__方法的都是object类的后代,因此如果我们自己想要改写__new__方法(注意不改写时在创建实例的时候使用的是父类的__new__方法,如果父类没有则继续上溯)可以通过调用object的__new__方法类得到这个实例(这实际上也和python中的默认机制基本一致),如:

class display(object):
  def __init__(self, *args, **kwargs):
    print("init")
  def __new__(cls, *args, **kwargs):
    print("new")
    print(type(cls))
    return object.__new__(cls, *args, **kwargs)  
a=display()

运行上述代码会得到如下输出:

new

<class 'type'>

init

因此我们可以得到如下结论:

在实例创建过程中__new__方法先于__init__方法被调用,它的第一个参数类型为type。

如果不需要其它特殊的处理,可以使用object的__new__方法来得到创建的实例(也即self)。

于是我们可以发现,实际上可以使用其它类的__new__方法类得到这个实例,只要那个类或其父类或祖先有__new__方法。

class another(object):
  def __new__(cls,*args,**kwargs):
    print("newano")
    return object.__new__(cls, *args, **kwargs)  
class display(object):
  def __init__(self, *args, **kwargs):
    print("init")
  def __new__(cls, *args, **kwargs):
    print("newdis")
    print(type(cls))
    return another.__new__(cls, *args, **kwargs)  
a=display()

上面的输出是:

newdis
<class 'type'>
newano
init

所有我们发现__new__和__init__就像这么一个关系,__init__提供生产的原料self(但并不保证这个原料来源正宗,像上面那样它用的是另一个不相关的类的__new__方法类得到这个实例),而__init__就用__new__给的原料来完善这个对象(尽管它不知道这些原料是不是正宗的)

Python 相关文章推荐
python编程开发之textwrap文本样式处理技巧
Nov 13 Python
Python找出list中最常出现元素的方法
Jun 14 Python
Mac 上切换Python多版本
Jun 17 Python
python解决字符串倒序输出的问题
Jun 25 Python
Python 中的range(),以及列表切片方法
Jul 02 Python
使用PyCharm创建Django项目及基本配置详解
Oct 24 Python
python实现石头剪刀布小游戏
Jan 20 Python
Flask框架学习笔记之使用Flask实现表单开发详解
Aug 12 Python
python实现一个函数版的名片管理系统过程解析
Aug 27 Python
Python嵌套函数,作用域与偏函数用法实例分析
Dec 26 Python
Python使用Selenium实现淘宝抢单的流程分析
Jun 23 Python
Python with语句用法原理详解
Jul 03 Python
Python中的ConfigParser模块使用详解
May 04 #Python
Python的__builtin__模块中的一些要点知识
May 02 #Python
一些Python中的二维数组的操作方法
May 02 #Python
在Python的Tornado框架中实现简单的在线代理的教程
May 02 #Python
探究Python的Tornado框架对子域名和泛域名的支持
May 02 #Python
Python编程中运用闭包时所需要注意的一些地方
May 02 #Python
按日期打印Python的Tornado框架中的日志的方法
May 02 #Python
You might like
php addslashes 函数详细分析说明
2009/06/23 PHP
php防盗链的常用方法小结
2010/07/02 PHP
注意:php5.4删除了session_unregister函数
2013/08/05 PHP
php生成随机颜色的方法
2014/11/13 PHP
Yii框架日志记录Logging操作示例
2018/07/12 PHP
php基于 swoole 实现的异步处理任务功能示例
2019/08/13 PHP
php在linux环境中如何使用redis详解
2020/12/15 PHP
PHP实现爬虫爬取图片代码实例
2021/03/03 PHP
基于jQuery图片平滑连续滚动插件
2009/04/27 Javascript
当鼠标滑过文本框自动选中输入框内容的JS代码分享
2013/11/26 Javascript
Jquery 获取指定标签的对象及属性的设置与移除
2014/05/29 Javascript
网页禁用右键菜单和鼠标拖动选择方法小结
2015/02/25 Javascript
JavaScript使用cookie实现记住账号密码功能
2015/04/27 Javascript
jQuery中 delegate使用的问题
2015/07/03 Javascript
js实现iPhone界面风格的单选框和复选框按钮实例
2015/08/18 Javascript
vue项目中使用ueditor的实例讲解
2018/03/05 Javascript
微信网页登录逻辑与实现方法
2019/04/29 Javascript
JS中getElementsByClassName与classList兼容性问题解决方案分析
2019/08/07 Javascript
JavaScript链式调用原理与实现方法详解
2020/05/16 Javascript
python爬虫请求头的使用
2020/12/01 Python
Python实现疫情地图可视化
2021/02/05 Python
CSS3绘制有活力的链接下划线
2016/07/14 HTML / CSS
HTML5之SVG 2D入门13—svg对决canvas及长处和适用场景分析
2013/01/30 HTML / CSS
德国宠物用品、宠物食品及水族馆网上商店:ZooRoyal
2017/07/09 全球购物
父亲生日宴会答谢词
2014/01/10 职场文书
体育教学随笔感言
2014/02/24 职场文书
合作协议书
2014/04/23 职场文书
中国梦我的梦演讲稿
2014/04/23 职场文书
运动会跳远广播稿5篇
2014/09/17 职场文书
党的群众路线教育实践活动总结材料
2014/10/30 职场文书
教师个人培训总结
2015/02/11 职场文书
2015年党支部书记工作总结
2015/05/21 职场文书
委托开发合同书(标准版)
2019/08/07 职场文书
3招让你摆脱即兴讲话冷场尴尬
2019/08/08 职场文书
导游词之五台山
2019/10/11 职场文书
python编程项目中线上问题排查与解决
2021/11/01 Python