1、当子类继承了父类,子类重写了父类的______init__方法,但是大多数子类不仅要拥有自己的初始化代码,还要拥有超类的初始化代码。父类的构造方法在子类中是不会被自动调用的,需要子类专门去调用父类的构造方法。这样才能将父类正确初始化。
下面看一个例子:
class Bird(object):
def __init__(self):
self.hungry = True
def eat(self):
if self.hungry:
print 'Aaaah...'
self.hungry = False
else:
print 'No, thanks.'
if __name__ == '__main__':
b = Bird()
b.eat()
b.eat()
运行结果如下:
C:\Python27\python.exe I:/OOP/jicheng/ex_03.py
Aaaah...
No, thanks.
这个类定义了鸟最基本的能力,下面我们定义一个会唱歌的鸟,继承它。
class
SongBird(Bird):
def __init__(self):
self.sound = 'Squawk'
def sing(self):
print self.sound
if __name__ == '__main__':
sb = SongBird()
sb.sing()
# 下面我们调用父类继承来的方法
sb.eat()
运行结果如下:
C:\Python27\python.exe I:/OOP/jicheng/ex_03.py
Traceback (most recent call last):
File "I:/OOP/jicheng/ex_03.py", line 33, in <module>
sb.eat()
File "I:/OOP/jicheng/ex_03.py", line 11, in eat
if self.hungry:
AttributeError: 'SongBird' object has no attribute 'hungry'
Squawk
通过错误结果显示,SongBird这个类没有hungry这个属性。为什么继承子父类的,怎么回没有这个属性呢?
就像我们前面说的那样,子类必须显示的调用父类的构造方法赖初始化父类才行。
子类中构造方法被重写,但是新的构造方法没有任何关于初始化hungry特征的代码。为了达到预期的效果,子类的构造方法必须调用其父类的构造方法赖确保进行基本的初始化,
有两种方法:
方法一:调用超类方法的未绑定版本
方法二:使用super函数。
2、
方法一:
我们先在子类中添加下面一行代码
class SongBird(Bird):
def __init__(self):
Bird.__init__(self)
self.sound = 'Squawk'
def sing(self):
print self.sound
在子类中添加了一行Bird.init(self)。再执行
C:\Python27\python.exe I:/OOP/jicheng/ex_03.py
Squawk
Aaaah...
No, thanks.
这次执行正确了。
当我们在使用实例调用实例的方法时,该方法的self参数就会被自动绑定到该实例上,self就代表当前实例。这样叫作绑定方法。
但是如果直接使用类名.方法(比如 Bird.init)这样就不会将self实例绑定。这样就可以自由的提供所需要的self参数了。
通过将当前实例(就是SongBord的实例)作为参数给未绑定方法,SongBird就可以使用父类的构造方法的所有实现。hungry属性就可以被设置。
方法二:使用super()函数
class SongBird(Bird):
def __init__(self):
super(SongBird, self).__init__()
self.sound = 'Squawk'
def sing(self):
print self.sound
运行结果:
C:\Python27\python.exe I:/OOP/jicheng/ex_03.py
Squawk
Aaaah...
No, thanks.
和方法一的效果一样。但是super()函数比在超类中直接调用未绑定方法更直观。