zoukankan      html  css  js  c++  java
  • python之面向对象三大特性: 继承(单继承)

    什么是继承

    专业角度: B 继承 A类, B就叫做A的子类,派生类, A叫做B的父类,基类,超类. B类以及B类的对象使用A类的所有的属性以及方法.

    字面意思: 继承就是继承父母所有的资产

    class Person:
    		    def __init__(self,name,sex,age):
            self.name = name
            self.age = age
            self.sex = sex
    
    class Dog:
    		    def __init__(self,name,sex,age):
            self.name = name
            self.age = age
            self.sex = sex
    	
    class Cat:
    		    def __init__(self,name,sex,age):
            self.name = name
            self.age = age
            self.sex = sex
    

    继承的优点(用途)

    • 节省代码,减少代码的重复性
    • 增强耦合性(也就是增强代码可读性)
    • 使代码更加规范化
    • 子类可以调用父类的所有属性

    以上定义三个类,人类,狗类,猫类,发现以上代码有很多重复代码,三个类都有一样的属性,就要将重复代码合起来,重新定义一个动物类,那么就可以删除多余的代码,改成以下这种的

    继承的用法

    class Animal:
    		live = '有生命的'
    		def __init__(sefl, name, age, sex):
    				self.name = name
    				self.age = age
    				self.sex = sex
    		
        def eat(self):
        		print('动物都需要进食')
    class Person(Animal): # 括号中Animal就是父类
    		pass
    
    class Dog(Animal): # 括号中的Animal就是父类
    		pass
    	
    class Cat(Animal): # 括号中的Animal就是父类
    		pass
    		
    # 类名后面括号中传入的参数就是父类
    
    # 1. 从类名执行父类的属性
    先打印一下Person类中所有的属性
    print(Person.__dict__) #输出结果:{'name': '小胖', 'age': 18, 'sex': '男'}
    
    print(Persion.live) # 输出结果:有生命的
    
    # 2. 类名可以执行父类的方法
    Person.eat(555)
    
    # 3. 从对象执行父类的一切
    实例化对象一定会执行三件事.一定会执行__init__
    p1 = Person('dsb', 21, 'boy')
    print(p1.__dict__)
    print(p1.live)
    p1.eat()
    print(f'p1 ---> {p1}')
    
    # 注意: 子类以及子类对象只能调用父类的属性以及方法,不能操作(增删改).
    

    继承的分类

    单继承

    多继承

    Person Dog Cat:就叫做子类或者派生类

    Animal:就叫做父类,基类,超类

    单继承的用法

    class Aniaml(object):
        live = '有生命的'
    
        def __init__(self,name,sex,age):
                self.name = name
                self.age = age
                self.sex = sex
    
        def eat(self):
            print(f'self ---> {self}')
            print('吃东西')
    
    
    class Person(Aniaml):
       	def eat(self):
       		print('人类需要进食')
    
    
    class Cat(Aniaml):
        pass
    
    
    class Dog(Aniaml):
        pass
    
    p1 = Person('dsb', 21, 'boy')
    p1.eat()
    # 输出结果
    人类需要进食
    
    # 说明一个问题: 子类将父类的方法,覆盖了,(重写父类的方法) 查找位置
    # 对象查找顺序,先从对象空间找名字,子类找名字,父类找名字
    
    方法一: 第三个继承
    人类的不同于其他狗类和猫类的特性
    如何既要执行父类方法又要执行子类方法
    class Aniaml(object):
        live = '有生命的'
    
        def __init__(self,name,sex,age):
                self.name = name
                self.age = age
                self.sex = sex
    
        def eat(self):
            print(f'self ---> {self}')
            print('吃东西')
    
    
    class Person(Aniaml):
       	def eat(self):
       			print('人类需要进食')
    		
    		def __init__(self,name, age, sex, hobby):
    		
    				Aniaml.__init__(self, name, age, sex) # 关键点,手动的把对象空间传给self,但是()中需要接收参数
    				
    				self.hobby = hobby
    
    
    
    class Cat(Aniaml):
        pass
    
    
    class Dog(Aniaml):
        pass
    
    # 正常子类有__init__就不执行父类的__init__,现在的目的既要执行父类方法又要执行子类方法
    p1 = Person('催牛逼') # 这里的传参方法:p1 = Person('对对哥', 23, '不详','吹牛逼')
    print(p1.__dict__)
    
    
    # 方法二
    
    class Aniaml(object):
        live = '有生命的'
    
        def __init__(self, name, sex, age):
            self.name = name
            self.age = age
            self.sex = sex
    
        def eat(self):
            print(f'self ---> {self}')
            print('吃东西')
    
    
    class Person(Aniaml):
        def eat(self):
            print('人类需要进食')
    
        def __init__(self, name, age, sex, hobby):
        
          	super(Person, self).__init__(name,age,sex) # 关键点
          	# 简写成super().__init__(name, age, sex) # 使用了父类的init
            self.hobby = hobby
    
    
    class Cat(Aniaml):
        pass
    
    
    class Dog(Aniaml):
        pass
    
    
    # 正常子类有__init__就不执行父类的__init__,现在的目的既要执行父类方法又要执行子类方法
    p1 = Person('对对哥', 23, '不详', '吹牛逼')
    print(p1.__dict__)
    
    

    一句话总结

    单继承是为节省代码而设计的,定义一个公共的父类,但是如果子类中存在于父类中相同的方法,子类中的方法会将父类中的方法进行覆盖,对象在查找名字的时候先重对象空间查找name,如果有直接引用,如果没有继续从子类空间中查找name,如果还没有就继续从父类空间中查找name

    多继承的用法

    class God:
    	
    		def __init__(self, name):
    				self.name = name
    		
    		def fly(self):
    				print('会飞')
    		
    		def climb(self):
    				print('神仙累了也需要爬树')
    
    class Monkey:
    		
    		def __init__(self,sex):
    				self.sex = sex
    		
    		def climb(self):
        		print('爬树')
    class MonkeySun(God,Monkey): # 继承了2个类,孙猴子既是神仙又是猴子
    		pass
    		
    # 多继承的难点就是继承顺序的问题
    # 现在执行的时候是先执行神仙的还是先执行猴子的呢?
    
    这里面就涉及到单进程与多进程的分类:
    面向对象:
    python2.2之前都是经典类
    python2.2之后到python2.7之间存在2种类型:经典类,新式类.区别:经典类是基类,不继承object,它的查询规则,依靠的是深度优先的原则,
    python3x之后新式类,新式类必须继承object,查询规则是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 表尾: []

    工作中研究新式类的四算方法

    例题

    '''
    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()
    # a.func()
    '''
    '''
    mro(A) = mro(A(B,C))
           = [A] + merge(mro(B), mro(C), [B,C])
    
    mro(B) = mro(B(D,E))
           = [B] + merge(mro(D), mro(E), [D,E])
           = [B] + merge([D,O], [E,O], [D,E])
           = [B,D] + merge([O], [E,O], [E])
           = [B,D,E,O]
           
    mro(C) = mro(C(E,F))
           = [C] + merge(mro(E), mro(F),[E,F])
           = [C] + merge([E,O],[F,O],[E,F])
           = [C,E] + merge([O],[F,O],[F])
           = [C,E,F,O]
    
    mro(A) = mro(A(B,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,O]
    
  • 相关阅读:
    ios数据处理 简单文件处理
    ios硬件开发 照相机图像选取器(UIImagePickerController)的用法
    ios UI设计与开发 卷动视图
    ios数据处理 使用SQLite保存学生信息
    ios数据处理 Application preferfences
    ios数据处理 SQLite基本知识
    GDI+ 为了阴影和透明,使用双层窗口遇到的一些问题
    MFC CToolTipCtrl 总是显示
    遍历删除文件夹及文件
    WebService远程调试
  • 原文地址:https://www.cnblogs.com/zanao/p/11227534.html
Copyright © 2011-2022 走看看