类的多态继承
Python中,没有绝对的共有和私有,以及权限划分。所谓的共有、私有、内部变量都是通过约定是实现的。
- def method() 约定为共有方法
- def _method() 约定为私有方法,不期望外部使用,在代码中应该尽量避免使用内部变量和方法
- def __method 为类方法,只属于当前类
某年月,忽然有个小小明要来找小明认亲了
---------------------------------------
小小明
--------------------属性----------------
父亲:超人小明
母亲:阿花
--------------------方法----------------
来历:小明入魔后,阿花来唤醒他。然后。。。
滚出去:毕竟是亲生的,这个设定也遗传了
唤醒小明:继承自母亲的能力,以血缘唤回小明
- 属性说明:
- 小小明继承了 父亲:超人小明 和 母亲:阿花 两个人的基本属性
- 方法说明:
- 来历: 小明作为一个独立的人,能准确说出小明和阿花的爱恨情仇
- 滚出去:毕竟是亲生的嘛
- 唤醒小明:继承自母亲的能力
- 补充说明:
- 即便小小明是小明亲生的,小小明也不可能完全继承小明的所有能力,这些在代码中表现为私有属性/方法
- 比如老婆、比如变身成超人、比如和阿花的关系。。。
1 #! coding:utf-8 2 class SuperManXiaoMing(object): 3 4 def __init__(self): 5 self.name = "小明" 6 self.age = 40 7 self._lovesOther = ["阿芳", "阿花"] 8 self.__wife = "阿芳" 9 self._favor = "对18-28年轻漂亮的女孩子特别专一" 10 11 def goOut(self): 12 return "谁敢让本超人滚出去!" 13 14 def __beSuperMan(self): 15 return "小明长大了,变成了一个好多妹子喜欢的超人小明" 16 17 def _sayLoves(self): 18 for love in self._lovesOther: 19 print ("{}, 我是{}, 我爱你".format(love, self.name)) 20 21 class AHua(object): 22 23 def __init__(self): 24 self.name = "阿花" 25 self.age = 35 26 self._money = "穷是我的色彩" 27 28 def call_XiaoMing_back(self): 29 ''' 30 太肉麻,写不出来,自己脑补吧 31 :return: 32 ''' 33 return "小明,你还记得你说永远不会伤害我嘛" 34 35 class XiaoXiaoMing(SuperManXiaoMing, AHua): 36 37 def __init__(self, lovesOther): 38 SuperManXiaoMing.__init__(self) 39 AHua.__init__(self) 40 self.name = "小小明" 41 self.age = "10" 42 self._lovesOther = lovesOther 43 44 def goOut(self): 45 return "我可是超人的儿子!好吧,我滚就是了" 46 47 def call_XiaoMing_back(self): 48 return "阿爹,你站着别动,我去买点橘子" 49 50 def where_Im_from_(self): 51 return "我爹叫{}, 我妈叫{},他们是在一个月黑风高的晚上。。。。".format(SuperManXiaoMing().name, AHua().name) 52 53 def __beSuperMan(self): 54 return "我还没长大呢" 55 56 if __name__ == '__main__': 57 xiao = XiaoXiaoMing(["小丽"]) 58 print ("我叫{},今年{}。你们不要欺负我,因为{}".format(xiao.name, xiao.age, xiao.where_Im_from_())) 59 xiao._sayLoves() 60 print(xiao.call_XiaoMing_back()) 61 print(xiao.goOut()) 62 #----------------------------------output---------------------------- 63 # 我叫小小明,今年10。你们不要欺负我,因为我爹叫小明, 我妈叫阿花,他们是在一个月黑风高的晚上。。。。 64 # 小丽, 我是小小明, 我爱你 65 # 阿爹,你站着别动,我去买点橘子 66 # 我可是超人的儿子!好吧,我滚就是了 67 68 print(xiao._SuperManXiaoMing__beSuperMan()) 69 print(xiao._XiaoXiaoMing__beSuperMan()) 70 #----------------------------------output---------------------------- 71 # 小明长大了,变成了一个好多妹子喜欢的超人小明 72 # 我还没长大呢
注意:
- 在上述例子中,SuperManXiaoMing中的__beSuperMan只属于SuperManXiaoMing类,无法被子类继承
- 所有的私有和共有属性都可以被继承
super 和 parentClass.__init__的区别
上述例子中,XiaoXiaoMing 的初始化,采用的是显示初始化
class XiaoXiaoMing(SuperManXiaoMing, AHua): def __init__(self, lovesOther): SuperManXiaoMing.__init__(self) AHua.__init__(self)
当然,也可以使用super做隐式初始化
class XiaoXiaoMing(SuperManXiaoMing, AHua): def __init__(self, lovesOther): super().__init__(self)
这两种的区别为:
显示调用会顺序执行所有父类的方法,在多继承的情况下,甚至会出现多次执行的父类初始化方法的情况,隐式调用就只会执行一次
示例代码如下:
ParentClass.__init__方式
#! coding:utf-8 class Man(object): def __init__(self): print("Man.__init__") class BaBa(Man): def __init__(self): Man.__init__(self) print("BaBa.__init__") class MaMa(Man): def __init__(self): Man.__init__(self) print ("MaMa.__init__") class You(BaBa,MaMa): def __init__(self): BaBa.__init__(self) MaMa.__init__(self) print("You.__init__") you = You() # ----------------------------------output---------------------------- # Man.__init__ # BaBa.__init__ # Man.__init__ # MaMa.__init__ # You.__init__
可以看出,Man.__init__被调用了两次
Super().__init__方式
class Man(object): def __init__(self): print("Man.__init__") class BaBa(Man): def __init__(self): super().__init__() print("BaBa.__init__") class MaMa(Man): def __init__(self): super().__init__() print ("MaMa.__init__") class You(BaBa,MaMa): def __init__(self): super().__init__() print("You.__init__") you = You() # ----------------------------------output---------------------------- # Man.__init__ # MaMa.__init__ # BaBa.__init__ # You.__init__
Man.__init__只调用了一次
多继承中初始化参数的问题
上述例子中,Super的情况仅适用于 两个父对象的初始化方法参数相同,如果参数不同的话要怎样做呢?
一种做法是如之前例子中显式的初始化每一个父类,并单独赋值
class XiaoXiaoMing(SuperManXiaoMing, AHua): def __init__(self, lovesOther, husband): SuperManXiaoMing.__init__(self, lovesOther) AHua.__init__(self,husband)
另一种做法是使用Super进行单独赋值
class XiaoXiaoMing(SuperManXiaoMing, AHua): def __init__(self, lovesOther, husband): super().__init__(lovesOther) super(SuperManXiaoMing, self).__init__(husband)
这种写法不会减少父类的重复调用
super方法在初始化时遵循MRO算法,
在 MRO 中,基类永远出现在派生类后面,如果有多个基类,基类的相对顺序保持不变
如上述例子中,super的执行顺序就是
XiaoXiaoMing --> SuperManXiaoMing --> Ahua
|
|-----> XiaoMing
super().__init__()默认参数为当前类,指的是第二个类SuperManXiaoMing,等价于 super(XiaoXiaoMing,self).__init__()
如果赋值为SuperManXiaoMing, super(SuperManXiaoMing, self).__init__()就指的是 Ahua
使用如下方式进行查看
class XiaoXiaoMing(SuperManXiaoMing, AHua): def __init__(self, lovesOther, husband): print(super()) super().__init__(lovesOther) super(SuperManXiaoMing, self).__init__(husband)