需求
当在Python中写类操作时,普通的类操作并不会用到的,当类之间继承操作时,第一个父类__init__里面定义的变量在子类继承时无法获取指定的变量,从而导致错误,下面是一堆官方解释,有耐心的话继续阅读。
在我看来,相比于直接对超类调用未关联方法,使用函数super更直观,但这并非其唯一的优点。实际上,函数super很聪明,因此即便有多个超类,也只需调用函数super一次(条件是所有超类的构造函数也使用函数super)。另外,对于使用旧式类时处理起来很棘手的问题
(如两个超类从同一个类派生而来),在使用新式类和函数super时将自动得到处理。你无需知道函数super的内部工作原理,但必须知道的是,使用函数super比调用超类的未关联构造函数(或其他方法)要好得多。
函数super返回的到底是什么呢?通常,你无需关心这个问题,只管假定它返回你所需的超类即可。实际上,它返回的是一个super对象,这个对象将负责为你执行方法解析。当你访问它的属性时,它将在所有的超类(以及超类的超类,等等)中查找,直到找到指定的属性或
引发AttributeError异常。
解决方案
super实现
# -*- coding: utf-8 -*-
class Birds():
def __init__(self):
self.hungry = True
def eat(self):
if self.hungry:
print("Aaaah ...")
self.hungry = False
else:
print("No thanks")
class SongBird(Birds):
def __init__(self):
super().__init__()
self.sound = "Squawk!"
def sing(self):
print(self.sound)
sb = SongBird()
sb.sing()
sb.eat()
sb.eat()
重构构造函数
# -*- coding: utf-8 -*-
class Birds():
def __init__(self):
self.hungry = True
def eat(self):
if self.hungry:
print("Aaaah ...")
self.hungry = False
else:
print("No thanks")
class SongBird(Birds):
def __init__(self):
# super().__init__()
self.sound = "Squawk!"
def sing(self):
print(self.sound)
sb = SongBird()
sb.sing()
sb.eat()
异常
Squawk!
Traceback (most recent call last):
File "/application/working/python/Algorithms/day06/class01.py", line 24, in <module>
sb.eat()
File "/application/working/python/Algorithms/day06/class01.py", line 7, in eat
if self.hungry:
AttributeError: 'SongBird' object has no attribute 'hungry'
原因
异常清楚地指出了问题出在什么地方: SongBird没有属性hungry。为何会这样呢?因为在SongBird中重写了构造函数,但新的构造函数没有包含任何初始化属性hungry的代码。要消除这种错误, SongBird的构造函数必须调用其超类( Bird)的构造函数,以确保基本的初始化得以执行。为此,有两种方法:调用未关联的超类构造函数,以及使用函数super。接下来的两节将介绍这两种方法。