• 20181214(继承,派生)


     

    派生/继承/继承结构

    派生描述了子类衍生出新的特性,新类保留已存类类型中所有需要的数据和行为,但允许修改或者其它的自定义操作,都不会修改原类的定义。 继承描述了子类属性从祖先类继承这样一种方式 继承结构表示多“代”派生,可以述成一个“族谱”,连续的子类,与祖先类都有关系。

     

    一、继承

    1、定义:继承是一种类与类之间的关系,是一种新建类的的方式,在python中支持一个儿子继承多个爹,即多继承。

    新建的类称为子类或者派生类, 父类又可以称为基类或者超类。

    子类会”遗传“父类的属性

     

    2、使用继承的好处:减少代码冗余

    3、使用继承的方法:

    class Father:  # 定义一个父类
       pass
    class FatherWang:  # 定义另一个父类
       pass

    # 在子类中,类名后面括号内写上父类的名称即可
    # 在python中,存在多个父类时,括号内用逗号隔开即可。其他语言不支持这个操作
    class Son1(Father): # 单继承,基类是Father,派生类是Son1
       pass

    class Son2(Father,FatherWang): #子类继承了两个父类
       pass

    # 子类可以使用父类的属性和函数
    # 如果子类中有,优先从子类中拿取,子类中没有,就从父类中拿取

    class Parent:
       year = 2018
       def coding(self):
           print("coding...")

    class Sub(Parent): # Parent的子类Sub
       year = 2019

    print(Parent.year)  # 注意调取参数的语法
    print(Sub.year)
    s = Sub()  # 先从类中创建一个对象
    print(s.year)  # 对象优先从其类中查找数据,没有的去父类中寻找
    s.coding()
    输出结果:
    2018
    2019
    2019
    coding...

     

    4、查看继承

    __base__只查看从左到右继承的第一个子类,__bases__则是查看所有继承的父类.

    交互模式下输入:

    >>> class Father:pass
    ...
    >>> class FatherWang:pass
    ...
    >>> class Son(Father,FatherWang): pass
    ...
    >>> Son.__bases__
    (<class '__main__.Father'>, <class '__main__.FatherWang'>)
    >>> Son.__base__
    <class '__main__.Father'>

     

    二、继承与抽象

    通过继承,避免了重复代码的编写 #从父类中继承得到了一些基础属性 通过抽象,避免了继承到一些不该有的内容 #抽象即抽取类似部分或者比较像的部分。 应该先抽象再具体

    (继承是拿到父类的属性,如果想要修改也可以自己修改;抽象就是尽可能求同,找出普适性的共同点,将其通过描述(定义变量或函数)确定下来(父类))

     

    三、派生

    派生:子类定义自己新的属性,如果与父类同名,以子类自己的为准。派生类是子类的一种,添加、修改了自己独有的属性的子类就是派生类。

     

    在子类中,新建的重名的函数属性,在编辑函数内功能的时候,有可能需要调用父类中重名的那个函数功能。此时用调用普通函数的方式,即:类名.func(),此时就与调用普通函数无异了,因此即便是self参数也要为其传值。

     

    派生与覆盖:

    子类出现与父类重复的名字 称之为覆盖 子类出现与父类不重复的名字 称之为派生

     

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

    class Student(Person):  # 这是派生,有自己的内容
       def __init__(self,name,age,number):
           Person.__init__(self,name,age)  
           self.number = number
           
    class Student1(Person):  # 这不是派生,因为没有自己的内容
    pass
         

     

    四、子类访问父类中的方法

    两种方法,两种函数。

     

    指名道姓调用函数:其实与继承没有什么关系。

     

    super函数:super().__init__(name,age) 创建一个特殊的对象,用于调用父类的方法。

    在python2 中,需要传入当前类和当前对象,super(Student,self).__init__(name,age,sex)

     

    两种方法的区别:方式一其实和继承没有关系,方式二super()是依赖于继承的,即使没有继承关系,也会按照mro算法继续向后查找。

    方法一:注意传参方式
    class Person:
       def __init__(self,name,age):
           self.name = name
           self.age = age

    class Student(Person):
       def __init__(self,name,age,number):
           Person.__init__(self,name,age)  # 直接调用Person中的函数
           self.number = number  # Person中没有的则需要子类自己处理



    sut = Student("alex",33,110)
    print(sut.__dict__)

    方法二:注意传参方式
    class Person:
       def __init__(self,name,age):
           self.name = name
           self.age = age

    class Student(Person):
       def __init__(self,name,age,number):
           super().__init__(name,age)  # 此处传参没有self!
           self.number = number



    sut = Student("alex",33,110)
    print(sut.__dict__)

    两种方法的区别:

    #指名道姓
    class A:
       def __init__(self):
           print('A的构造方法')
    class B(A):
       def __init__(self):
           print('B的构造方法')
           A.__init__(self)
    class C(A):
       def __init__(self):
           print('C的构造方法')
           A.__init__(self)
    class D(B,C):
       def __init__(self):
           print('D的构造方法')
           B.__init__(self)
           C.__init__(self)
       pass

    f1=D() #A.__init__被重复调用
    '''
    D的构造方法
    B的构造方法
    A的构造方法
    C的构造方法
    A的构造方法
    '''


    #使用super()
    class A:
       def __init__(self):
           print('A的构造方法')
    class B(A):
       def __init__(self):
           print('B的构造方法')
           super(B,self).__init__()
    class C(A):
       def __init__(self):
           print('C的构造方法')
           super(C,self).__init__()
    class D(B,C):
       def __init__(self):
           print('D的构造方法')
           super(D,self).__init__()

    f1=D() #super()会基于mro列表查找,mro是一种算法,具体可以谷歌。
    '''
    D的构造方法
    B的构造方法
    C的构造方法
    A的构造方法
    '''

     

    五、存在继承关系后的属性查找

    先找对象,然后找类,然后找父类,然后是父类的父类(沿着继承关系)。。。直到报错

     

    class Foo:
       def f1(self):
           print('Foo.f1')
       def f2(self):
           print('Foo.f2')
           self.f1()
    class Bar(Foo):
       def f1(self):
          print('Bar.f1')

    b=Bar()
    b.f2()

    输出结果:
    Foo.f2
    Bar.f1    #self为b,所以是b.f1(),Bar().f1()        

     

    当存在多个父类时,按照继承顺序,从左到右,依次查找
    class A:
       a=1
    class B:
       a=2
    class C(A,B):
       print(a)
    输出结果为:
    1

     

    六、经典类与新式类

    1.只有在python2中才分新式类和经典类,python3中统一都是新式类

    2.在python2中,没有显式的继承object类的类,以及该类的子类,都是经典类

    3.在python2中,显式地声明继承object的类,以及该类的子类,都是新式类

    4.在python3中,无论是否继承object,都默认继承object,即python3中所有类均为新式类

    object称之为根类 ,意为所有类都源自于object类。

     

    七、菱形继承

    存在共同父类时,在菱形继承中,会先深度再广度继承

    如果在父类中,既有菱形又有非菱形,先按照继承顺序查找,碰到菱形时 就先广度再深度。

     

     

     

  • 相关阅读:
    git init 与 git init --bare 区别
    python_集合_笔记
    git笔记
    screen命令
    python的and和or优先级
    计算机语言的发展史
    python3颜色输出
    mysql_windows解压包安装
    那些经常不开心的上班族
    mysql主从搭建
  • 原文地址:https://www.cnblogs.com/realadmin/p/10121390.html
Copyright © 2020-2023  润新知