• Python 面向对象(其五)


    类的多态继承

    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)
  • 相关阅读:
    从 0 → 1,学习Linux该这么开始!
    Web和移动开发的未来
    css-div中文字过多(内容超出div宽度)后自动换行
    js+css--单选按钮,自定义选中的颜色???(性别按钮,男女)
    css-按钮中有图片和文字,怎么才能让文字和图片都中??
    js-点出弹框后(除了点击窗口上的叉子),点其他地方能够关闭窗口???
    css-外面元素的高度,由里面的元素进行撑开(由内部的高度决定)
    js-将传来的数据排序,让(全部)这个小按钮小圈圈,始终排列在最前面
    echart--如何在折线图上添加矩形背景(可以借用bar柱状图的实现效果)
    echart-如何将x轴和y轴的原点进行重合???
  • 原文地址:https://www.cnblogs.com/SilenceCity/p/pythonOO5.html
Copyright © 2020-2023  润新知