#!/usr/bin/env python # coding: utf-8 # # 继承与复用 # 在自定义类型的基本形式中: # # ```python # class ClassName(ParentClass): # """class docstring""" # def some_method(self, ...): # return ... # ``` # # ParentClass是用来进行继承的,被继承的ParentClass是父类,定义的ClassName是子类。可以认为子类是一种特殊的父类。 # # 例如,假设父类是哺乳动物,人作为一个子类可以继承这个父类,因为人是哺乳动物的一种;狮子也可以继承哺乳动物,因为狮子也是哺乳动物的一种。 # ## 类的继承 # 考虑这样一个表示树叶的类: # In[1]: class Leaf(object): def __init__(self, color='green'): self.color = color def fall(self, season="autumn"): print(f"A leaf falls in {season}!") # 继承这个类,生成一个枫树叶类: # In[2]: class MapleLeaf(Leaf): def change_color(self): if self.color == "green": self.color = "red" # 构造一个子类对象: # In[3]: mleaf = MapleLeaf() # 子类会继承父类的属性和方法,父类的属性和方法可以直接调用: # In[4]: mleaf.fall() # In[5]: mleaf.color # 子类虽然没有定义构造函数,但是会直接继承父类的构造函数: # In[6]: mleaf2 = MapleLeaf("orange") # In[7]: mleaf2.color # 子类额外定义的方法: # In[8]: mleaf.change_color() # In[9]: mleaf.color # ## 方法的重载 # 子类可以对父类中已有的方法进行重载。例如,在枫树叶类中对`.fall()`方法进行重载,即重新定义: # In[10]: class MapleLeaf(Leaf): def change_color(self): if self.color == "green": self.color = "red" def fall(self, season="autumn"): self.change_color() print(f"A leaf falls in {season}!") # 在这个例子中,`.fall()`方法被重载,并调用了自定义类中的已有方法。方法定义中的第一个参数`self`表示的就是对象自身,所以可以用`self.change_color()`实现对已有方法的调用: # In[11]: mleaf = MapleLeaf() # In[12]: mleaf.color # In[13]: mleaf.fall() # In[14]: mleaf.color # ## super()函数 # 与父类的.fall()方法相比,子类的方法只增加了.change_color()的调用,之后的操作与父类的.fall()方法一致,代码其实有冗余和浪费。Python提供了`super()`函数,在子类中调用父类的方法。具体定义如下: # In[15]: class MapleLeaf(Leaf): def change_color(self): if self.color == "green": self.color = "red" def fall(self, season="autumn"): self.change_color() super(MapleLeaf, self).fall(season) # print(f"A leaf falls in {season}!") # 能实现与上面一样的结果: # In[16]: mleaf = MapleLeaf() # In[17]: mleaf.color # In[18]: mleaf.fall() # In[19]: mleaf.color # ## 鸭子类型:一切都是为了复用 # # 鸭子类型(Duck Type)的概念来源于美国诗人詹姆斯·惠特科姆·莱利的诗句:“当看到一只鸟走起来像鸭子、游泳起来像鸭子、叫起来也像鸭子,那么这只鸟就可以被称为鸭子。”在Python中,这个概念被衍生为:在使用对象时,可以不关注对象的类型,而关注对象具有的方法或属性;只要对象的属性和方法满足条件,就认为该对象是合法的。 # # 例如,定义这样的一个函数: # In[20]: def something_fall(leaf): leaf.fall() # 这个函数接受一个参数leaf,并调用它的.fall()方法。Leaf类支持.fall()方法,因此该类型的对象是合法的: # In[21]: leaf = Leaf() # In[22]: something_fall(leaf) # 子类MapleLeaf也支持.fall()方法,所以也是合法的对象: # In[23]: mleaf = MapleLeaf() # In[24]: something_fall(mleaf) # 再定义一个类苹果: # In[25]: class Apple(object): def fall(self): print("An apple falls!") # In[26]: apple = Apple() # In[27]: something_fall(apple) # 在鸭子类型机制下,Python将函数和方法中的类型检查,变成了接口检查的模式,即something_fall()函数不会检查传入的参数leaf是什么类型,而是检查leaf有没有实现.fall()接口。 # In[ ]: