很早就遇到了这个函数了,一直想写写这个函数的。但又觉得没必要,毕竟这个函数理解起来不难。直到我今天读到一篇文章:听说你会 Python ?有兴趣的可以去看看。
在文章里面提到了一个问题(代码我修改了一下下),就是使用了super()函数,读者们可以试着解解下面这道题:
class Init(object):
def __init__(self, x):
self.x = x
class Add(Init):
def __init__(self, x):
super(Add, self).__init__(x)
self.x += 2
class Mul(Init):
def __init__(self, x):
super(Mul, self).__init__(x)
self.x *= 5
class Sub(Mul, Add):
def __init__(self, x):
super(Sub, self).__init__(x)
self.x -= 5
class Div(Sub):
fsup = super(Sub)
def __init__(self, x):
self.fsup.__init__(x)
self.x /= 5
test = Div(5)
print(test.x)
答案:7.0
如果这个你解出来了,那么恭喜,这篇文章不用看了。
如果不懂,没关系,跟着我魔鬼的步伐一起来看看这个super()到底是什么鬼东东。
一.继承
这个不用多说,不懂的猛戳这个连接:python的继承
给个例子理解一下:
class A(object):
def __init__(self):
print("Enter A")
print("Exit A")
class B(A):
def __init__(self):
print("Enter B")
A.__init__(self)
print("Exit B")
b = B()
结果如图:
但是上面存在一个问题就是,假如我们修改了A类的名字,比如换成了C。这样我们就需要到子类B去修改A的名字了。上面的例子还好,子类B只需修改两次就OK了。但在实际开发中,项目比较大,有时一个子类要多次调用父类,这么一来,A的名字一旦被修改,那么要到子类B修改A的名字简直就是一个吃力不讨好的活。所以super()函数应运而生。
二.super()函数
上面例子说明了为什么要用super()。好,接下来开始使用super()函数了。
请看下面例子:
class A(object):
def __init__(self):
print("Enter A")
print("Exit A")
class B(A):
def __init__(self):
print("Enter B")
super(B, self).__init__()
print("Exit B")
b = B()
结果和第一个例子一样。但是如果A的名字如过修改。只需在子类修改一次A的名字就好了。
来点有难度的:
class People(object):
def __init__(self, name):
self.name = name
def introduce(self):
print("My name is %s!" % self.name)
class Student(People):
def __init__(self, name, id):
super(Student, self).__init__(name)
self.id = id
def introduce(self):
super(Student, self).introduce()
print("My ID is %s" % self.id)
s = Student('Lifei', 123456)
s.introduce()
结果:
这个例子可以比较好的说明为什么要使用super()。如果我们不使用,那么在子类Student中修改People这个类名将要修改三次。如果子类大量调用父类的方法那么一旦需要修改,简直就是噩梦。上面两个例子我们只需修改第一行中的父类名字就可以了
三.深入了解super()
看到这里我们还是无法解决文章开头所提到的问题。
我们来看一个例子:
class A(object):
def __init__(self):
print("Enter A")
print("Exit A")
class B(A):
def __init__(self):
print("Enter B")
super(B, self).__init__()
print("Exit B")
class C(A):
def __init__(self):
print("Enter C")
super(C, self).__init__()
print("Exit C")
class D(B, C):
def __init__(self):
print("Enter D")
super(D, self).__init__()
print("Exit D")
d = D()
结果:
这里有个问题就是为什么B类中初始化并不是A,而是跑去初始化C了呢!
凡事都有规范。当然类的继承也是一样的。只不过是通过方法解析顺序(Method Resolution Order, MRO)列表来实现的。这个就是生成了一个顺序列表,至于底层算法怎么样,我们不要去管他。只需知道他帮助我们将类的关系排好了队。
super(cls, type)传入cls类在表中的下一个类。
我们可以执行下以下代码
print(D.mro())
结果
[<class '__main__.D'>, <class '__main__.B'>, <class '__main__.C'>, <class '__main__.A'>, <class 'object'>]
所以类的初始化就是按照这个表中的顺序去进行的。当执行到B类时,程序会在B的mro()列表里面寻找到下一个类,然后进入。
**mro遵循的原则:
1.子类永远在父类前面
2.如果有多个父类,会根据它们在列表中的顺序被检查
3. 如果对下一个类存在两个合法的选择,选择第一个父类
当然,super()再调用的时候是可以简写为下面例子的,效果一模一样:
class A(object):
def __init__(self):
print("Enter A")
print("Exit A")
class B(A):
def __init__(self):
print("Enter B")
super().__init__()
print("Exit B")
class C(A):
def __init__(self):
print("Enter C")
super().__init__()
print("Exit C")
class D(B, C):
def __init__(self):
print("Enter D")
super().__init__()
print("Exit D")
博文参考:
python super()
听说你会 Python ?
有问题探讨的请加QQ:1043601529