当开始使用 Python 的类(class)解决问题时,通常会遇到需要修改类的情况,这往往会导致原始类变得复杂或破坏原有功能。这时就需要使用类中的“继承”方式来处理。这篇教程将介绍 Python 中的“继承”。
什么是继承(inheritance)?
继承,就像字面上的意思:父亲继承了爷爷的东西,儿子继承父亲的东西...不断继承下去,继承表示可以用现有的类去定义一个新的类,并加入一些新的东西或修改新的类。当使用继承时,新类会自动使用旧类内所有的代码。
下面的代码,名为 son 的类使用class son(father)
的语法,继承了 father 的代码。当 oxxo 为 son 时,就能调用出 father 的所有属性。
class father(): # fatehr 类
def __init__(self):
self.eye = 2
self.ear = 2
self.nose = 1
self.mouth = 1
class son(father): # son 类继承了 fatehr 类里所有的方法
def language(self): # son 类具有 language 的方法
print('chinese') # 从 father 继承了五官,然后自己学会讲中文
oxxo = son() # 设定 oxxo 为 son()
print(oxxo.eye) # 打印出 2
oxxo.language() # 打印出 chinese
继承时会覆盖方法
在继承时,如果子类中的某个方法的名称和父类相同,就会完全复写父类的方法。下面的代码,son 类使用了 init 的方法,就覆盖了原本 father 的 init 方法,导致读取 oxxo.ear 时发生错误(因为 son 的方法里不存在 ear 的属性)。
class father():
def __init__(self):
self.eye = 2
self.ear = 2
self.nose = 1
self.mouth = 1
class son(father):
def __init__(self): # 使用了 __init 的方法
self.eye = 100
oxxo = son()
print(oxxo.eye) # 100
print(oxxo.ear) # 发生错误 'son' object has no attribute 'ear'
使用 super()
如果不想要覆盖父类的方法,又想要使用父类的方法,就可以使用super()
来实现。下面的代码,使用 super()继承了 father init 里所有的属性,然后再将 eye 的属性覆盖为 100。
class father():
def __init__(self):
self.eye = 2
self.ear = 2
self.nose = 1
self.mouth = 1
class son(father):
def __init__(self):
super().__init__() # 使用 super() 继承 father __init__ 里所有属性
self.eye = 100 # 如果属性相同,则覆写属性
oxxo = son()
print(oxxo.eye) # 100
print(oxxo.ear) # 2
多重继承
继承不仅可以进行单一继承,也可以进行多重继承,例如可以从爸爸身上继承基因,同时也可以妈妈身上继承基因。一般情况下,下面的例子,son 从 father 继承了五官,从 mother 继承了 language 和 skill。
class father(): # father 类
def __init__(self): # father 的方法
self.eye = 2
self.ear = 2
self.nose = 1
self.mouth = 1
class mother(): # mother 类
def language(self): # mother 的方法
print('english')
def skill(self):
print('painting')
class son(father, mother): # 继承 father 和 mother
def play(self): # son 自己的方法
print('ball')
oxxo = son()
print(oxxo.eye) # 2
oxxo.skill() # painting
oxxo.play() # ball
进行多重继承时,同样会有“覆盖方法”的情况出现,而覆盖方法的顺序是由“读取类的顺序”决定的,举个例子来说,下面的 c 和 d 两个类,虽然都多重继承了 a 和 b,但是因为读取的顺序不同,所以呈现的结果也会不同。
class a():
def says(self):
print('a')
class b():
def says(self):
print('b')
class c(a, b): # 先读取 a 再 b,就会将 a 里的方法,覆写 b 里同名的方法
pass
class d(b, a): # 先读取 b 再 a,就会将 b 里的方法,覆写 a 里同名的方法
pass
ccc = c()
ddd = d()
ccc.says() # a
ddd.says() # b
多层继承
继承中除了多重继承,也有“多层继承”的概念,就如同父亲继承了爷爷的东西,儿子继承父亲的东西,多层继承同样存在覆盖方法的原则,如果遇到同名的方法就会覆盖,除非使用 super()的方法处理,下面的例子里,father 继承了 grandpa 的五官,son 又继承了 father 的方法,最后 son 就拥有 father 和 grandpa 所有的方法。
class grandpa():
def __init__(self):
self.eye = 2
self.ear = 2
self.nose = 1
self.mouth = 1
class father(grandpa):
def language(self):
print('english')
def skill(self):
print('painting')
class son(father):
def play(self):
print('ball')
oxxo = son()
print(oxxo.eye) # 2
oxxo.skill() # painting
oxxo.play() # ball
私有方法(双下划线)
在实现一个类的过程中,可能会遇到有些方法是该类内部使用,不想让继承该类的子类可以使用的,这时就需要定义“私有方法”,私有方法可以使用“双下划线+名称”来定义,私有方法定义后,无论是从外部读取或是子类的继承,都无法使用该方法,只有在该类里的其他方法才能调用。
下面的代码 grandpa 有一个__money 的方法,但除非知道 getMoney 的方法,不然都无法直接读取(爷爷有一笔钱,除非你知道方法,否则无法继承成功)。
class grandpa():
def __init__(self):
self.mouth = 1
def __money(self): # 定义一个私有方法 __money
print('$1000')
def getMoney(self): # 定义一个 getMoney 的方法,执行私有方法 __money
self.__money()
class father(grandpa):
def skill(self):
print('painting')
class son(father):
def play(self):
print('ball')
oxxo = son()
oxxo.getMoney() # $1000
oxxo.__money() # 发生错误 'son' object has no attribute '_money'