super()是一个什么鬼?干什么用的?打开菜鸟教程看一下super()的简介;第一句话就是:super()函数是用来调用父类(超类)的一个方法。嗯哦;原来是一个函数可以返回一个父类的方法:于是我就这样理解了,那么如果是多继承呢,是返回所有父类的被调用的方法吗?一个疑问?看看下面的代码(先定义一个人类,然后定义一个男人,一个女人,一个儿子)
class Person(object): #定义一个人类,继承objec def __init__(self): print("我要好好学习") def study(self): print("我要学好语言") class man(Person): #定义一个男人,继承人类 def __init__(self): print("我是男人我要好好学习") def study(self): print("我要学好数学") class woman(Person): #定义一个女人,继承人类 def __init__(self): print("我是女人我要好好学习") def study(self): print("我要学好英语") class son(man,woman): #定义一个儿子,继承男人和女人 def __init__(self): print("我是儿子我要好好学习") def study(self): print("我要学好化学和物理")
# woman.study(self) # man.study(self) super().study() # def study1(self): # print("我要学好英语") son1 = son() son1.study() # son1.study1()
解释:先定义一个人类,定义一个方法:我要学好语言;然后定义一个男人:我要学好数学;再定义一个女人:我要学好英语;最后定义一个儿子学好化学和物理;在定义方法的时候我们都使用了study函数;所以子类的函数 会覆盖父类的函数;最后实例化一个son1的对象调用study函数只会输出:我要学好化学和物理;但是这个时代光会这两门也不行啊;还得学好英语啊,那么怎么办呢? ok 简单 在这个son的类中增加一个study1函数不就完了嘛,嗯,对确实完了;但是这样却增加了不必要的代码啊,学习英语这件事woman类中不是有了吗?我们不能直接使用这里的吗?当然可以,于是有了第二种方法: 在son的类中的study函数中增加了 woman.study(self) 这句好相当于直接调用woman类中的study函数 同理也可以直接调用man类中的study函数;这样就不用创建新函数了;这种等于直接调用。我们还可以使用另外 一种方式来调用man和woman中的study函数即:super().study();前面两种我们已经注释掉了我们只研究最后一种;即出现了上面的代码;那么这段代码会 出现什么呢?(反正我一开始觉得super()不是调用父类的方法嘛,既然son有两个父类,两个父类的study函数一起调用了呗,可是结果呢)
代码执行结果:
我是儿子我要好好学习 我要学好化学和物理 我要学好数学
噫噫噫,不对啊,和我想的不一样啊,只返回了man类中的方法;没有返回woman类中的方法啊;这是什么情况呢?一百的问号????
于是查看了很多的博客,毕竟还是有很多大神的嘛我们要向前辈们学习啊,于是对super()又有了新的认识:我们返回文章的第一句话,super()是个什么鬼?从新解释一下:super()不是一个函数而是一个类,super()相当于这个类调用了自己的初始化函数,返回了一个对象;这个对象是干嘛的呢,用来调用实例化对象中的mro()序列中的下一个 的 类的指定的类中的方法(mro()返回的是一个:方法解析顺序列表)估计又懵了,那么我们先打印一下:son.mro()
[<class '__main__.son'>, <class '__main__.man'>, <class '__main__.woman'>, <class '__main__.Person'>, <class 'object'>]
实际上打印出来的就是son的继承父类的顺序(son---man---woman---Person---object)
那么以本例来说在son中写了super(),那么son的下一个mro当然就是man类,所以就返回了man类中的study方法了。这就是上面那个疑问的解答了;那么问题又来了如果我在man类中也写了super().study(),那么接下来会打印什么呢?无非就两个可能一个是打印Person中的sutdy方法另一个可能就是打印woman类中的study方法(为什么是这两种呢,如果我们是以son为出发点man的下一个mro当然是woman;但是我们现在是把super().study()写在了man类中这个时候好像以man类为出发点也说的过去啊,那么我们先打印一下man,mro()。)
class man(Person): def __init__(self): print("我是男人我要好好学习") def study(self): print("我要学好数学") super().study() 结果: [<class '__main__.man'>, <class '__main__.Person'>, <class 'object'>]
果然man的下一个mro是Person而不是woman啊,如果我们执行上面的代码最终到底是打印person呢还是woman呢?看结果:
我是儿子我要好好学习 [<class '__main__.son'>, <class '__main__.man'>, <class '__main__.woman'>, <class '__main__.Person'>, <class 'object'>] [<class '__main__.man'>, <class '__main__.Person'>, <class 'object'>] 我要学好化学和物理 我要学好数学 我要学好英语
打印出来的是我要学好英语是woman中的(而不是person中的);如果我们在woman类中也一起写上super(),那么:
class Person(object): def __init__(self): print("我要好好学习") def study(self): print("我要学好语言") class man(Person): def __init__(self): print("我是男人我要好好学习") def study(self): print("我要学好数学") super().study() class woman(Person): def __init__(self): print("我是女人我要好好学习") def study(self): print("我要学好英语") super().study() class son(man,woman): def __init__(self): print("我是儿子我要好好学习") def study(self): print("我要学好化学和物理") # woman.study(self) # man.study(self) super().study() # def study1(self): # print("我要学好英语") son1 = son() print(son.mro()) print(man.mro()) son1.study() # son1.study1()
结果:
我是儿子我要好好学习 [<class '__main__.son'>, <class '__main__.man'>, <class '__main__.woman'>, <class '__main__.Person'>, <class 'object'>] [<class '__main__.man'>, <class '__main__.Person'>, <class 'object'>] 我要学好化学和物理 我要学好数学 我要学好英语 我要学好语言
看一下结果就知道了先打印了man类中的study方法,之后打印了woman类中的方法;最后打印了Person类中的study方法;所以到这里暂时得到一个结论:super()不是指父类(对于man类来说Person应该是父类)而只指以实例化对象为起点的mro序列中的下一个。
那么我们把上面的代码再来改一改,如果我把man类中的super()注释掉了,但是woman类中保留着super()会又什么样的的结果呢:
class Person(object): def __init__(self): print("我要好好学习") def study(self): print("我要学好语言") class man(Person): def __init__(self): print("我是男人我要好好学习") def study(self): print("我要学好数学") # super().study() class woman(Person): def __init__(self): print("我是女人我要好好学习") def study(self): print("我要学好英语") super().study() class son(man,woman): def __init__(self): print("我是儿子我要好好学习") def study(self): print("我要学好化学和物理") # woman.study(self) # man.study(self) super().study() # def study1(self): # print("我要学好英语") son1 = son() print(son.mro()) print(man.mro()) son1.study() # son1.study1()
结果:
我是儿子我要好好学习 [<class '__main__.son'>, <class '__main__.man'>, <class '__main__.woman'>, <class '__main__.Person'>, <class 'object'>] [<class '__main__.man'>, <class '__main__.Person'>, <class 'object'>] 我要学好化学和物理 我要学好数学
结果是man类中的sutdy方法打印出来了然而woman和Person类中的study方法没有打印出来;相当与 son--man--woman中在man这里打断了,然后后面的也就不执行了。
好吧就到这里吧由于刚开始学习python,对于super()理解的还有很多不到位的地方;以后这篇文章还需要改进,暂时理解到这个程度。