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'>]
    
    

  • 相关阅读:
    爬取校园新闻首页的新闻的详情,使用正则表达式,函数抽离
    网络爬虫基础练习
    Mysql 使用 select into outfile
    Mysql 使用CMD 登陆
    使用Clean() 去掉由函数自动生成的字符串中的双引号
    Get Resultset from Oracle Stored procedure
    获取引用某个主键的所有外键的表
    Entity Framework 丢失数据链接的绑定,在已绑好的EDMX中提示“Choose Your Data Connection”
    添加MySql Metat Database 信息
    at System.Data.EntityClient.EntityConnection.GetFactory(String providerString)
  • 原文地址:https://www.cnblogs.com/dengz/p/11158348.html
Copyright © 2011-2022 走看看