python中对象⽅法的定义很怪异,第⼀个参数⼀般都命名为self(相当于其它语⾔的this),⽤于传递对象本⾝,有时候还会有⼀个参数cls(相当于类名,当直接调⽤类⽅法的时候使⽤)。python2中super()的⽤法: super(class,self).__init__()python3中super()的⽤法: super().__init__()
在类的继承⾥⾯super()⾮常常⽤, 它解决了⼦类调⽤⽗类⽅法的⼀些问题, ⽗类多次被调⽤时只执⾏⼀次。def super(cls, inst):
mro = inst.__class__.mro() return mro[mro.index(cls) + 1]
当使⽤ super(cls, inst) 时,Python 会在 inst 的类的 MRO 列表上搜索 cls 的下⼀个类。⽽查看inst类的的MRO列表的⽅法就是:类.mro() 或 类.__mro__ 或 inst.__class__.mro()例如:当C是⼀个类的时候,获得⼀个类的MRO的⽅法是C.mro() 或 C.__mro__ 或 C().__class__.mro()
执⾏过程:
当执⾏⽣成D的inst对象的时候,先执⾏Enter D
这个时候D类的MRO列表为[ 当执⾏super(D,self) 就是在self对象的类的MRO列表中查找D的下⼀个⽗类。这个self是D类的实例对象inst。 ⽽D类中的MRO列表中D的下⼀个⽗类是B。例如: 1、super单继承的时候: class A: def __init__(self): self.n = 2 def add(self, m): print('self is {0} @A.add'.format(self)) self.n += m class B(A): def __init__(self): self.n = 3 def add(self, m): print('self is {0} @B.add'.format(self)) super().add(m) self.n += 3b = B()b.add(2)print(b.n) 结果是什么呢? 为什么是8? 执⾏b.add(2)的时候,执⾏A中的add()函数,执⾏的时候这个时候的self是b这个实例,所以这个self.n是3所以执⾏3+2=5 然后执⾏super的下⼀句5+3=8。2、super多继承的时候 #super的多继承class A: def __init__(self): self.n = 2 def add(self, m): print('self is {0} @A.add'.format(self)) self.n += m class B(A): def __init__(self): self.n = 3 def add(self, m): print('self is {0} @B.add'.format(self)) super().add(m) self.n += 3 class C(A): def __init__(self): self.n = 4 def add(self, m): print('self is {0} @C.add'.format(self)) super().add(m) self.n += 4class D(B, C): def __init__(self): self.n = 5 def add(self, m): print('self is {0} @D.add'.format(self)) super().add(m) self.n += 5d = D()d.add(2)print(d.n) 这个结果是什么呢? 我认为是5+B.add+C.add+A.add+5=5+3+4+2+5=19看下输出的结果: 执⾏过程是什么样的呢?详细的代码分析如下: class A: def __init__(self): self.n = 2 def add(self, m): print('self is {0} @A.add'.format(self)) self.n += m#第4步执⾏,A.add(2),这个时候self=b,n=5,即n=5+2=7class B(A): def __init__(self): self.n = 3 def add(self, m): print('self is {0} @B.add'.format(self)) super().add(m)#第2步执⾏,相当于super(B,d),在d的MRO[D,B,C,A,Object]中B的下⼀个C.add(2),这个时候self=b,n=5 self.n += 3 #第6步执⾏,n=11+3=14class C(A): def __init__(self): self.n = 4 def add(self, m): print('self is {0} @C.add'.format(self)) super().add(m)#第3步执⾏,相当于super(C,d),在d的MRO[D,B,C,A,Object]中C的下⼀个A.add(2),这个时候self=b,n=5 self.n += 4 #第5步执⾏,n=7+4=11class D(B, C): def __init__(self): self.n = 5 def add(self, m): print('self is {0} @D.add'.format(self)) super().add(m)#第1步执⾏相当于super(D,d)这个时候就会返回在d的MRO[D,B,C,A,Object]中D的下⼀个类B,执⾏B.add(2) self.n += 5 #第7步执⾏,n=14+5=19d = D() print(d.__class__.mro())#[D, B, C, A,object]d.add(2)print(d.n) 当我们调⽤ super() 的时候,实际上是实例化了⼀个 super 类 在⼤多数情况下, super 包含了两个⾮常重要的信息: ⼀个 MRO 以及 MRO 中的⼀个类。当以如下⽅式调⽤ super 时:super(a_type, obj) MRO 指的是 type(obj) 的 MRO, MRO 中的那个类就是 a_type , 同时 isinstance(obj, a_type) == True 。当这样调⽤时:super(type1, type2) MRO 指的是 type2 的 MRO, MRO 中的那个类就是 type1 ,同时 issubclass(type2, type1) == True 。 那么, super() 实际上做了啥呢?简单来说就是:提供⼀个 MRO 以及⼀个 MRO 中的类 C , super() 将返回⼀个从 MRO 中 C 之后的类中查找⽅法的对象。 也就是说,查找⽅式时不是像常规⽅法⼀样从所有的 MRO 类中查找举个例⼦, 有个 MRO:[A, B, C, D, E, object]下⾯的调⽤:super(C, A).add() super 只会从 C 之后查找,即: 只会在 D 或 E 或 object 中查找 add ⽅法 因篇幅问题不能全部显示,请点此查看更多更全内容