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

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

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

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

例子:

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

1
2
3
4
5
6
7
8
9
10
11
>>> 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)

1
2
3
4
5
6
7
8
9
10
11
>>> 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中的默认机制基本一致),如:

1
2
3
4
5
6
7
8
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__方法。

1
2
3
4
5
6
7
8
9
10
11
12
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()

上面的输出是:

1
2
3
4
newdis
<class 'type'>
newano
init

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

http://www.qytang.com/
http://www.qytang.com/cn/list/29/
http://www.qytang.com/cn/list/28/404.htm
http://www.qytang.com/cn/list/28/397.htm
http://www.qytang.com/cn/list/28/396.htm
http://www.qytang.com/cn/list/28/395.htm
http://www.qytang.com/cn/list/28/394.htm
http://www.qytang.com/cn/list/28/393.htm
http://www.qytang.com/cn/list/28/391.htm
http://www.qytang.com/cn/list/28/389.htm
http://www.qytang.com/cn/list/28/388.htm
http://www.qytang.com/cn/list/28/362.htm
http://www.qytang.com/cn/list/28/358.htm
http://www.qytang.com/cn/list/28/351.htm
http://www.qytang.com/cn/list/28/348.htm
http://www.qytang.com/cn/list/28/340.htm
http://www.qytang.com/cn/list/28/338.htm
http://www.qytang.com/cn/list/28/336.htm
http://www.qytang.com/cn/list/28/330.htm

python2中的__new__与__init__,新式类和经典类-乾颐堂的更多相关文章

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

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

  2. python2中新式类和经典类的多重继承调用顺序

    class A: def foo(self): print('called A.foo()') class B(A): pass class C(A): def foo(self): print('c ...

  3. python单例模式控制成只初始化一次,常规型的python单例模式在新式类和经典类中的区别。

    单例模式的写法非常多,但常规型的单例模式就是这样写的,各种代码可能略有差异,但核心就是要搞清楚类属性 实例属性,就很容易写出来,原理完全一模一样. 如下: 源码: class A(object): d ...

  4. Python中的__new__和__init__

    Python中的__new__和__init__ 写了这么多的class,现在才知道还有个__new__方法, 那么它和__init__有什么区别呢? class TestCls(): "& ...

  5. python中新式类和经典类

    python中的类分为新式类和经典类,具体有什么区别呢?简单的说, 1.新式类都从object继承,经典类不需要. Python 2.x中默认都是经典类,只有显式继承了object才是新式类 Pyth ...

  6. python中新式类和经典类的区别

    1).python在类中的定义在py2-3版本上是使用的有新式类和经典类两种情况,在新式类和经典类的定义中最主要的区别是在定义类的时候是否出现引用object;如:经典类:Class 类名::而新式类 ...

  7. python之继承、抽象类、新式类和经典类

    一.上节补充1.静态属性静态属性 : 类的属性,所有的对象共享这个变量 如果用对象名去修改类的静态属性:在对象的空间中又创建了一个属性,而不能修改类中属性的值 操作静态属性应该用类名来操作 例1:请你 ...

  8. 面向对象【day07】:新式类和经典类(八)

    本节内容 1.概述 2.类的多继承 3.经典类VS新式类 4.总结 一.概述 在python还支持多继承,但是一般我们很少用,有些语言干脆就不支持多继承,有多继承,就会带来两个概念,经典类和新式类,下 ...

  9. python-反射、新式类与经典类搜索的优先级

    preface include: getattr setattr delattr hasattr class webserver(object): def __init__(self,num): se ...

随机推荐

  1. 网站建设之高速WEB的实现

    1.此文目的 漂亮的色彩.绚丽的动画在输入网址后便能呈现在你的眼前.互联网无可否认已经融入了我们的生活. 我们可以山寨出iPhone却很难有属于自己独特的理念关于事物的思想和心脏. 互联网是现实.艺术 ...

  2. Erlang generic standard behaviours -- gen_server hibernate

    hibernate 主要用于在内存空闲时,通过整理进程的stack,回收进程的heap 来达到回收内存节省资源的效果. hibernate 可用于OTP 进程以及普通进程, hibernate 的官方 ...

  3. 模拟Linux修改实际、有效和保存设置标识

    就是模拟setuid seteuid setreuid setresuid,感觉代码比书上大段的文字好记,就写成代码形式了. // setuid.cc: 模拟<unistd.h>中的设置用 ...

  4. 【AR实验室】mulberryAR :添加连续图像作为输入

    本文转载请注明出处 —— polobymulberry-博客园 0x00 - 前言 之前mulberryAR只能利用手机相机实时捕捉图像作为系统的输入,这也比较符合用户的习惯.但是在开发的过程中,有时 ...

  5. mysql字符集和校对规则(Mysql校对集)

    字符集的概念大家都清楚,校对规则很多人不了解,一般数据库开发中也用不到这个概念,mysql在这方便貌似很先进,大概介绍一下简要说明 字符集和校对规则 字符集是一套符号和编码.校对规则是在字符集内用于比 ...

  6. [转][Java]Maven使用阿里云镜像

    本文来自:http://www.cnblogs.com/justforcon/p/6792039.html <settings xmlns="http://maven.apache.o ...

  7. lamp与lnmp的选择

    lnmp和lamp业务上的不同 由于二者仅仅是区别在于web的选择,nginx更高效,占用资源更少,详情区别查看LNMP环境应用实践 lnmp和lamp安装上的不同 生产环境中,可能会遇到lamp架构 ...

  8. Android:自定义Sqlite数据库路径

    默认的sqlite数据库是放在/data/data/database目录下的,今天看腾讯云IM的demo发现再该路径下找不到它存放消息的数据库,找了下后发现居然是放在/data/data/files目 ...

  9. SSH框架的简化(struts2、spring4、hibernate5)

    目的: 通过对ssh框架有了基础性的学习,本文主要是使用注解的方式来简化ssh框架的代码编写. 注意事项: 1.本文提纲:本文通过一个新闻管理系统的实例来简化ssh框架的代码编写,功能包括查询数据库中 ...

  10. MySQL编码问题(无法插入中文)

    1.问题描述 2.解决方案 1.问题描述 当使用django时,如果数据库是MySQL,插入中文会报错: Incorrect string value: '\xF0\x9F...' for colum ...