zoukankan      html  css  js  c++  java
  • Python 继承、派生、组合、接口、抽象类

    继承是一种的关系,和组合对比,组合是一种的关系,这两者都是解决代用重用问题的

    继承

    注意:继承不是遗传,在显示角度中,是通过对象抽象成类,再把这些类抽象成一个,就是父类。是自下而上的过程,在程序中是首先由父类,然后由类,之后才有对象,是自上而下的过程。

    
    class classparent1:  #父类
        pass
    
    class classparent2:
        pass
    
    class useclass1(classparent1):  # 单继承
        pass
    
    class useclass2(classparent1,classparent2):  # 多继承
        pass
    
    print(useclass1.__bases__)
    print(useclass2.__bases__)
    

    结果:
    (<class 'main.classparent1'>,)
    (<class 'main.classparent1'>, <class 'main.classparent2'>)

    默认继承的是object类,Python3中都是新式类

    类实例化

    类实例化执行的时候首先从自己找,找不到从父类找。

    继承与重用性

    类中用的是父类的,不用重新写代码,实现了代码的复用。

    class Hero:
        def __init__(self,nickname,aggressivity,life_value):
            self.nickname = nickname
            self.aggressivity = aggressivity
            self.life_value =life_value
        def attack(self,enemy):
            enemy.life_value -= self.aggressivity
    
    class Garen(Hero):
            pass
    class Riven(Hero):
        camp = 'Noxus'
    
    g1 = Garen('garen',18,200)  # 实例化
    r1 = Riven('garen',18,200)
    

    派生

    在子类中添加新的功能属性,派生首先是继承一个父类,定义一个新的,定义一个父类重名的,都会从子类自己的地方找。

    class Hero:
        def __init__(self,nickname,aggressivity,life_value):
            self.nickname = nickname
            self.aggressivity = aggressivity
            self.life_value =life_value
    
    
        def attack(self,enemy):
            enemy.life_value -= self.aggressivity
    
    class Garen(Hero):
        camp = 'Ddemacia'
        def atatack(self,enemy):
            pass
        def fire(self):
            print('%s is fireing' %self.nickname)
    class Riven(Hero):
        camp = 'Noxus'
    
    g1 = Garen('garen',18,200)  # 实例化
    r1 = Riven('garen',18,200)
    g1.camp
    g1.atack(r1)  # 调用自己的,派生出新的功能
    

    在派生中调用

    子类继承了父类的方法,然后想进行修改,注意了是基于原有的基础上修改,那么就需要在子类中调用父类的方法

    方法1

    使用的是父类的的函数功能

    class Hero:
        def __init__(self, nickname,aggressivity,life_value):
            self.nickname = nickname
            self.aggressivity = aggressivity
            self.life_value = life_value
        def attack(self, enemy):
            print('Hero attack')
    class Garen(Hero):
        camp = 'Demacia'
    
        def attack(self, enemy): #self=g1,enemy=r1
            # self.attack(enemy) #g1.attack()  这是绑定方法  进入递归出错
            Hero.attack(self,enemy)    # 使用的是父类的attack  是函数,需要参数,selfs是上面传过来的
            print('from garen attack')
    
        def fire(self):
            print('%s is firing' % self.nickname)
    class Riven(Hero):
        camp = 'Noxus'
    g1 = Garen('garen', 18, 200)
    r1 = Riven('rivren', 18, 200)
    g1.attack(r1)
    

    对父类的init函数进行重用

    
    class Hero:
        def __init__(self, nickname, aggressivity, life_value):
            self.nickname = nickname
            self.aggressivity = aggressivity
            self.life_value = life_value
        def attack(self, enemy):
            print('Hero attack')
            enemy.life_value -= self.aggressivity
    # print(Hero.__init__)
    # print(Hero.attack)
    class Garen(Hero):
        camp = 'Demacia'
        def __init__(self, nickname, aggressivity, life_value, script):
            Hero.__init__(self,nickname,aggressivity,life_value)
            self.script = script
        def attack(self, enemy):  # self=g1,enemy=r1
            # self.attack(enemy) #g1.attack()
            Hero.attack(self, enemy)
            print('from garen attack')
        def fire(self):
            print('%s is firing' % self.nickname)
    # g1=Garen('garen',18,200) #Garen.__init__(g1,'garen',18,200)
    g1=Garen('garen',18,200,'人在塔在') #Garen.__init__(g1,'garen',18,200)
    print(g1.script)
    

    方法2 Spper

    python3 super

    #python3  super
    class People:
        def __init__(self,name,sex,age):
            self.name = name
            self.sex = sex
            self.age = age
    
        def walk(self):
            print("%s is walking"%self.name)
    
    class Chinese(People):
        country = 'china'
        def __init__(self,name,sex,age,language='Chinese'):
    
            super().__init__(name,sex,age)  # python3中不需要再super内部传参数
            self.language = language
        def walk(self,x):
            super().walk()   #
            print('子类的x',x)  #
    
    
    c = Chinese('aaa','male',18)
    c.walk(123)
    

    当你使用super()函数时,Python会在MRO列表上继续搜索下一个类。只要每个重定义的方法统一使用super()并只调用它一次,那么控制流最终会遍历完整个MRO列表,每个方法也只会被调用一次(注意注意注意:使用super调用的所有属性,都是从MRO列表当前的位置往后找,千万不要通过看代码去找继承关系,一定要看MRO列表

    python2中的额super

    #python2 的super用法:
    # super(自己的类,self).父类的函数名
    # super只能适用于新式类
    
    class People(object):  # python2中需要定义新式类
        def __init__(self,name,sex,age):
            self.name = name
            self.sex = sex
            self.age = age
    
        def walk(self):
            print("%s is walking"%self.name)
    
    class Chinese(People):
        country = 'china'
        def __init__(self,name,sex,age,language='Chinese'):
    
            super(Chinese,self).__init__(name,sex,age)  # python3中不需要再super内部传参数
            self.language = language
        # def walk(self,x):
        #     super().walk()   #
        #     print('子类的x',x)  #
    
    
    c = Chinese('aaa','male',18)
    print(c.name,c.age,c.language)
    

    组合

    组合指的是,在一个类中以另外一个类的对象作为数据属性,称为类的组合

    首先明确的是组合不是继承,是一种有的关系,是类与类之间的关系。

    '''
    不用组合的情况
    '''

    class Teacher:
        def __init__(self,name,sex,course_name,course_price,course_peroid):
            self.name =name
            self.sex = sex
            self.course_name=course_name
            self.course_price = course_price
            self.course_peroid = course_peroid
    class Student:
        def __init__(self,name,sex,course_name,course_price,course_peroid):
            self.name = name
            self.sex = sex
            self.course_name = course_name
            self.course_price = course_price
            self.course_peroid = course_peroid
    
    t1 = Teacher('egon','male',)
    s1 = Student('cobile','name',)
    
    print(s1.course.name)
    print(t1.course.name)
    

    使用类的情况

    # 使用组合重用代码
    class Course:    # 新建了一个课程类
        def __init__(self,name,price,peroid):
            self.name = name
            self.price = price
            self.peroid = peroid
    
    class Teacher:
        def __init__(self,name,sex,course):
            self.name =name
            self.sex = sex
            self.course=course
    class Student:
        def __init__(self,name,sex,course):
            self.name = name
            self.sex = sex
            self.course = course
    python_obj = Course('python',15800,'7m')  # 实例化课程类
    t1 = Teacher('egon','male',python_obj)  # 直接用的是python_obj这个对象
    s1 = Student('cobile','name',python_obj)  
    

    接口与归一化设计##

    继承有两种用途:

    一:继承基类的方法,并且做出自己的改变或者扩展(代码重用)

    二:声明某个子类兼容于某基类,定义一个接口类Interface,接口类中定义了一些接口名(就是函数名)且并未实现接口的功能,子类继承接口类,并且实现接口中的功能

    接口继承实质上是要求“做出一个良好的抽象,这个抽象规定了一个兼容接口,使得外部调用者无需关心具体细节,可一视同仁的处理实现了特定接口的所有对象”——这在程序设计上,叫做归一化。

    归一化使得高层的外部使用者可以不加区分的处理所有接口兼容的对象集合——就好象linux的泛文件概念一样,所有东西都可以当文件处理,不必关心它是内存、磁盘、网络还是屏幕(当然,对底层设计者,当然也可以区分出“字符设备”和“块设备”,然后做出针对性的设计:细致到什么程度,视需求而定)。

    抽象类

    这里用抽象类实现了接口的方法,抽象类是一个介于类和接口直接的一个概念,同时具备类和接口的部分特性,可以用来实现归一化设计

    抽象类是一个特殊的类,它的特殊之处在于只能被继承,不能被实例化

    如果说类是从一堆对象中抽取相同的内容而来的,那么抽象类就是从一堆类中抽取相同的内容而来的,内容包括数据属性和函数属性。

    抽象类用到了模块abc,装饰器

    #抽象类
    import abc
    class Animal(metaclass=abc.ABCMeta):
        tag = '123'
        @abc.abstractclassmethod
        def run(self):
            pass
        @abc.abstractclassmethod
        def speak(self):
            pass
    
    
    
    class People(Animal):
        def run(self):
            pass
        def speak(self):
            pass
    
    peo1 = People()
    print(peo1.tag)
    

    抽象类:本质还是类,与普通类额外的特点的是:加了装饰器的函数,子类必须实现他们

  • 相关阅读:
    YASKAWA电机控制(1)---接线
    Linux使用者管理(2)---账号管理
    OpenCV源码阅读(3)---base.hpp
    机器视觉基础(2)---坐标与矩阵变换
    Linux使用者管理(1)---用户账号
    OpenCV源码阅读(3)---matx.h---学习心得
    OpenCV源码阅读(2)---matx.h---函数的内联实现
    机器视觉基础(1)---投影
    shell编程基础(5)---循环指令
    HTML里 iframe跳转后关闭iframe
  • 原文地址:https://www.cnblogs.com/Python666/p/6740462.html
Copyright © 2011-2022 走看看