zoukankan      html  css  js  c++  java
  • Python进阶(十五)----面向对象之~继承(单继承,多继承MRO算法)

    Python进阶(十五)----面向对象之~继承

    一丶面向对象的三大特性:封装,继承,多态

    二丶什么是继承

    # 什么是继承
    	# b 继承 a ,b是a的子类 派生类  , a是b的超类 基类 父类
    	# b类或者b对象 能够使用 a类的所有属性和方法
    
    # 为什么要有继承
        由子类继承父类,从而完成了对子类功能的扩展
    
    #第一:
            子类对父类的继承是全部的公有和受保护的继承,这使得子类可能继承了对子类无用甚至有害的父类的方法。换句话说,子类只希望继承父类的一部分方法,怎么办?
    #第二:
            实际的对象千变万化,如果每一类的对象都有他们自己的类,尽管这些类都继承了他们的父类,但有些时候还是会造成类的无限膨胀。
    #第三:
            继承的子类,实际上需要编译期确定下来,这满足不了需要在运行内才能确定对象的情况。而组合却可以比继承灵活得多,可以在运行期才决定某个对象。
    #摘自: hivon博主
    
    
    # 总结:
        #  对类的功能的扩展,要多用组合,少用继承。
    

    三丶继承的优缺点

    #优点:
     	#1.节省代码, 2.增强耦合性 , 3. 代码规范化 , 4 .重构父类方法
     
    #缺点:
    	# 继承关系会造成 高耦合性
        
    

    转一篇关于 继承 优缺点的文章

    四丶单继承

    ## 单继承
    class Animal:
        live = '活着'
    
        def __init__(self, name, sex, age):
            self.name = name
            self.sex = sex
            self.age = age
    
        def eat(self):
            print('in eat function')
    
    
    class Person(Animal):
        pass
    
    
    ### 1. 子类以及对象 可以调用父类的方法和属性
    
    print(Person.live)  		# 子类名.父类中的属性 , 查看或获取父类中的变量
    Person.eat('d')  			# 子类名.父类中的方法,调用父类的方法
    print(Person.__dict__)		# 查看 子类中 存在的属性
    
    
    ### 2. 从对象执行父类的一切.
    # 实例化对象一定一定会执行三件事. 一定会执行__init__
    p1 = Person('ly', '男', '21')
    print(p1.live)  # 对象调用 类中的属性
    p1.eat()  # 对象 调用类中的方法
    print(p1.__dict__)      # 查看 p1对象的属性
    
    Person.live = 'xxx'
    print(Person.live)
    
    
    # 注意: 子类以及子类对象,只能调用父类的属性以及方法 , 不能操作增删改
    
    
    
    ## 单继承super的使用 ,
    class Animal:
        live = '活着'
        def __init__(self, name, sex, age): # self 接收的 p1 对象内存空间,给p1封装属性
            self.name = name
            self.sex = sex
            self.age = age
    
        def eat(self):
            print('in  父类  eat function')
    
    
    class Person(Animal):
        def __init__(self,name,age,sex,hobby):   # 给p1 封装 hobby属性
    
            # Animal.__init__(self,name,age,sex)   # 执行父类的 __init__方法 , self 是当前p1 对 .
            # super(Person, self).__init__(name,sex,age)
            super().__init__(name,sex,age)		#执行父类 __init__方法
    
            self.hobby=hobby
    
        def eat(self):
            print('子类吃')
            super().eat()
    
    
    p1=Person('ly','33','人妖','服务')
    p1.eat()
    print(p1.__dict__)				#打印p1对象中的属性, 父类定义的属性, 和子类自定义的属性 都存在
    
    

    五丶多继承

    python 2.2 之前: 都是经典类

    class A:		# 经典类    不继承object类
    	pass 
    

    python 2.2 直至 python2.7 之间存在两种类型:经典类,新式类

      经典类:

          基类不继承object ,查询规则:依靠深度优先(先深入继承树左侧查找,然后再返回,开始查找右侧)

      新式类:

          必须继承object , 查询规则: MRO算法

    class A:		# 经典类
    	pass
    
    class B(object):	#新式类
    	pass
    

    python3x 只有新式类

    class B(object): 	# 新式类   , (object) 默认可以不写    继承object类
    	pass
    
    
    
    ### 多继承案例
    class ShenXian: # 神仙
        def fei(self):
            print("神仙都会⻜")
    class Monkey: # 猴
        def chitao(self):
            print("猴⼦喜欢吃桃⼦")
    class SunWukong(ShenXian, Monkey): # 孙悟空是神仙, 同时也是⼀只猴
        pass
    sxz = SunWukong() # 孙悟空
    sxz.chitao() # 会吃桃⼦
    sxz.fei() # 会⻜
    

    ​ 多继承的难点就是继承顺序的问题

           MRO算法:

    #### 新式类 继承关系的运算
    ###  mro算法
    # 公式:
        # mro(Child(Base1,Base2)) = [ Child ] + merge( mro(Base1), mro(Base2), [ Base1, Base2] )
        # mro(Foo(H,G)) = [Foo] + merge(mro(H), mro(G),[H,G])
    
    
        
    # 表头:
    #   列表的第一个元素
    # 表尾:
    #   列表中表头以外的元素集合(可以为空)
    # 表头,表尾
    # [A,B,C] : 表头: A 表尾: [B,C]
    # [A] : 表头: A 表尾: []
    
    # +操作
    # [A] + [B] = [A, B]
    
    
    
    class O:
        pass
    
    class D(O):
        pass
    
    class E(O):
        pass
    
    class F(O):
        pass
    
    class B(D,E):
        pass
    
    class C(E,F):
        pass
    
    class A(B,C):
        pass
    
    a = A()
    
    
    
    
    #### 方式一 套用公式
    '''
    mro(A(B,C))=[A] + merge(mro(B) , mro(C)),   [B,C]    # merge(mro(B) , mro(C)) 放到下面拆解了
               =[A] + merge( [B,D,E,O] , [C,E,F,O]   ) ,[B,C] 
               =[A,B] + merge([D,E,O],[C,E,F,O]),[C]
               =[A,B,D] + merge([E,O],[C,E,F,O]),[C]
               =[A,B,D,C,] + merge([E,O],[E,F,O])
               =[A,B,D,C,E] + merge([O],[F,O])  
               =[A,B,D,C,E,F] + merge([O])
               =[A,B,D,C,E,F,O] 
                
    mro(B(D,E))=[B] + merge(mro(D),mro(E)), [D,E]               # C3算法, merge操作是C3算法的核心。
               =[B] + merge([D]+[O],[O] ,[E]+[O],[O]),[D,E]     # 公式拆解,
               =[B] + merge([D,O],[E,O]),[D,E]                  
               =[B,D] + merge([O],[E,O]),[E]
               =[B,D,E] + merge([O])
               =[B,D,E,O]
               
    mro(C[E,F])=[C] + merge(mro(E),mro(F)),[E,F]
               =[C] + merge([E]+megre([O]),[F]+megre([O])),[E,F]    
               =[C] + merge([E,O],[F,O]) ,[E,F]
               =[C,E] + merge([O],[F,O]),[F]
               =[C,E,F] + merge([O],[O])     
               =[C,E,F,O]     
    '''
    
    
    #### 方式二 使用 mro()
    print(A.mro())  # [<class '__main__.A'>, <class '__main__.B'>, <class '__main__.D'>, <class '__main__.C'>, <class '__main__.E'>, <class '__main__.F'>, <class '__main__.O'>, <class 'object'>]
    
    

  • 相关阅读:
    UVa 10088 (Pick定理) Trees on My Island
    LA 3295 (计数 容斥原理) Counting Triangles
    LA 5846 (计数) Neon Sign
    java是什么?软帝学院告诉你学Java能做什么?Java有什么特性?
    【软帝学院】一套好的java基础教学视频需要哪些有哪些内容
    推荐五个java基础学习网站,小白必备
    学习java设计模式有用吗?懂这六个原则,编程更轻松
    Java是什么?只需5分钟,了解java必须要知道的知识点
    软帝学院:自学java到底难不难?做好这几步,少走3年弯路
    软帝学院:java开发程序很难吗?学会这十步,5分钟搞定一个程序
  • 原文地址:https://www.cnblogs.com/dengz/p/11158348.html
Copyright © 2011-2022 走看看