python2中的__new__与__init__,新式类和经典类

在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代码制造configure文件
下一篇:Python的内建比较函数cmp比较原理分析

PythonTab微信大众号:

Python技能交流合作群 ( 请勿加多个群 ):

群1: 87464755

群2: 333646237

群3: 318130924

群4: 385100854