• python新式类和经典类的区别



    1,新式类和经典类的区别:
    广度优先和深度优先,这主要是在多类继承的时候会使用到,如下多类继承的D类对比:
    经典类在加载的时候采用的是深度优先算法,二新式类采用的是广度优先算法:比如
    经典类: 搜索顺序是(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
    (总结:
    1:经典类的深度优先,子类继承多个父类的时候,如果继承的多个类中有属性相同的,那么排在第一的父类的属性会覆盖后面继承的类的属性,也就是如果集成的多个父类属性相同,那么以继承的第一个父类的属性为主;
    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__给的原料来完善这个对象(尽管它不知道这些原料是不是正宗的)
     
  • 相关阅读:
    xdg-open filename 以相应的程序 打开文件
    列出zip文件内全部内容 当前目录下的所有文件压缩成zip格式的文件(file.zip)
    网线的制做
    多少天以后的时期和多少天以前的日期
    更数数据库用户密码
    tengine-2.1.0 源码安装
    inode
    mysql 查看用户的权限
    SQL Server 2008 R2占用内存越来越大两种解决方法
    SQL死锁知识及解决办法
  • 原文地址:https://www.cnblogs.com/qinjiting/p/10462573.html
Copyright © 2020-2023  润新知