zoukankan      html  css  js  c++  java
  • day24:继承

    1,复习1

    # 面向对象编程
    # 思想:角色的抽象,创建类,创建角色(实例化),操作这些示例
    # 面向对象的关键字
    
    class 类名:
        静态属性 = 'aaa'
        def __init__(self):pass
    
    类名.静态属性 # --储存在类的命名空间里
    对象 = 类名() # 实例化:创造了一个self对象,执行init方法,返回self对象给外部
    # 对象.属性
    # 对象.方法 绑定方法,方法和对象绑定到了一起 # 类名.方法(对象)
    # 对象可以使用静态变量?True
    # 类可以使用对象里的属性吗?False

    2,复习2

    # 组合
    # 一个类的对象是另外一个类的属性
    # 什么有什么的关系
    
    class A:
        def __init__(self):
            self.name = 'egon'
    
    class B:
        def __init__(self,year,month,day):
            self.year = year
            self.month = month
            self.day = day
    
    b = B(18,1,17)
    a = A()
    a.birth = b
    print(b.year)  # 18
    print(a.birth.year) # 18

    3,面向对象的三大特性:继承,多态和封装,非常非常重要的,计算机领域的三大特性

    什么是继承:继承是一种创建新类的方式,在Python中,新建的类可以继承一个或多个父类,父类又可称为基类或超类,新建的类称为派生类或子类

    class A:pass # 父类,基类,超类
    class B:pass # 父类,基类,超类
    class A_son(A,B):pass # 子类,派生类
    class AB_son(A):pass # 子类,派生类
    
    # 一个类 可以被多个类继承
    # 一个类 可以继承多个父类 ----这个只有Python里面才有
    
    print(A_son.__bases__)
    # (<class '__main__.A'>, <class '__main__.B'>)
    print(AB_son.__bases__)
    # (<class '__main__.A'>,)
    print(A.__bases__) 
    # (<class 'object'>,)

    4,类里面,刚开始加载类的时候,就从上到下把类里面的名字加载进去了,加载进去后才可以用类名.静态属性。占内存的也只是里面的变量名字而已

    5,object在类食物链的顶端, python3里面没有继承父类,默认继承object,这种累叫做新式类,object类是一个非常强大的类,里面实现了很多很多的内容,object里面有很多双下方法

    6,通常的继承都是我们自己写的类,但是到网络编程的时候,我们会接触到继承Python里面已经存在的类,例如str等

    7,抽象,抽取类似或者比较像的部分,抽象最主要的作用是划分类别,可以隔离关注点,降低复杂度

    8,类和类的关系叫做继承,类和对象的关系叫做实例化。

    class Animal:
        def __init__(self,name,aggr,hp):
            self.name = name
            self.aggr = aggr
            self.hp = hp
    
    class Dog(Animal):
        def bite(self,person):
            person.hp -= self.aggr
    
    class Person(Animal):
        pass
    
    jin = Dog('bossjin',200,500)  # 子类没有__init__方法,会去调用父类的双下init方法
    print(jin.name)

    9,子类和父类都有的方法,会优先调用谁的呢?这是一道面试题,传谁的self就运行谁的方法。

    class Animal:
        def __init__(self):
            print("执行Animal.__init__")
            self.func()
    
        def eat(self):
            print('%s eating'%self.name)
    
        def drinking(self):
            print("%s dringking"%self.name)
    
        def func(self):
            print("Animal.func")
    
    class Dog(Animal):
        def guard(self):  
            print('guarding')
    
        def func(self):
            print('Dog.func')
    
    dog = Dog()  # 这儿调用的是Dog类里面的func.因为self传得是dog

    运行结果:
    执行Animal.__init__
    Dog.func

    10,对于下面的问题怎么解决呢?

    class Animal:
        def __init__(self,name,aggr,hp):
            self.name = name
            self.aggr = aggr
            self.hp = hp
    
    class Dog(Animal):
        def __init__(self,name,aggr,hp,kind):
            self.kind = kind
    
        def bite(self,person):
            person.hp -= self.aggr
    
    
    jin = Dog('bossjin',200,500,'teddy')
    print(jin.name)  # AttributeError: 'Dog' object has no attribute 'name'
    # 错误原因,自己有了init就不会再去运行父类的init方法,

    11,派生属性

    class Animal:
        def __init__(self,name,aggr,hp):
            self.name = name
            self.aggr = aggr
            self.hp = hp
    
    class Dog(Animal):
        def __init__(self,name,aggr,hp,kind):
            Animal.__init__(self,name,aggr,hp) # 这个地方我们不仅完成了继承,还完成了派生,也就是一个派生属性,新添加的属性
            self.kind = kind
    
        def bite(self,person):
            person.hp -= self.aggr
    
    
    jin = Dog('bossjin',200,500,'teddy')
    print(jin.name) # bossjin

    12,除了有派生属性,还有派生方法,父类没有子类有的就是派生方法;父类中没有的属性,在子类中出现,叫做派生属性;父类中没有的方法,在子类中出现,叫做派生方法。

    只要是子类的对象调用,子类中有的名字,一定用子类的,子类中没有才找父类的,如果父类也没有,报错;如果父类子类都有,用子类的;如果还想用父类的,单独调用父类的,需要自己传self参数。

    13,既想实现新的功能,也想用父类的功能,需要单独调用父类的

    class Animal:
        def __init__(self,name,aggr,hp):
            self.name = name
            self.aggr = aggr
            self.hp = hp
    
        def eat(self):
            print("吃药回血")
            self.hp += 100
    
    class Dog(Animal):
        def __init__(self,name,aggr,hp,kind):
            Animal.__init__(self,name,aggr,hp) # 这个地方我们不仅完成了继承,还完成了派生,也就是一个派生属性,新添加的属性
            self.kind = kind # 派生属性
    
        def eat(self):
            Animal.eat(self)  # 如果既想实现新的功能也想使用父类原本的功能,还需要在子类中再调用父类
            self.teeth = 2
    
        def bite(self,person):  # 派生方法
            person.hp -= self.aggr
    
    
    jin = Dog('bossjin',200,500,'teddy')
    jin.eat()
    print(jin.teeth)

    14,另外一个调用父类方法的Python3中的用法,super,类内和类外都可以用,内部可以不传参,外部必传

    class Animal:
        def __init__(self,name,aggr,hp):
            self.name = name
            self.aggr = aggr
            self.hp = hp
    
        def eat(self):
            print("吃药回血")
            self.hp += 100
    
    class Dog(Animal):
        def __init__(self,name,aggr,hp,kind):
            super().__init__(name,aggr,hp)
            # self 不需要单独传了,super()意思是找我的父类,然后就可以调用父类的init了
            # 这个地方省略了两个参数 Dog类和self对象两个参数
            # super关键字只要新式类中有,不是Python3,Python中所有的类都是新式类,Python2中两种类共存
            # super还可以再类外面用
            self.kind = kind
    
        def eat(self):
            Animal.eat(self)
            self.teeth = 2
            print('son class')
    
        def bite(self,person):
            person.hp -= self.aggr
    
    
    jin = Dog('bossjin',200,500,'teddy')
    jin.eat()
    print(jin.teeth)
    super(Dog,jin).eat() # 这儿调用的是父类的eat方法。

    15,子类中调用父类方法两种:父类名.方法名 需要自己传self参数,super().方法名 类内不需要自己传self

    16,正常的代码中 单继承 ==减少了代码的重复,继承表达了一种子类是父类的关系,提到组合和继承一定是两个类以上的,看是“是”的关系还是“有”的关系。例如:老师有生日,狗是动物

    17,工作中用的一般都是单继承,多继承一般就是设计模式,或者面试中用到,多继承的继承顺序问题

    class A:
        def func(self):print('A')
    class B:
        def func(self):print('B')
    class C:
        def func(self): print('C')
    
    class D(A,B,C):
        def func(self): print('D')
    
    
    # 调用顺序
    print(D.mro())
    # [<class '__main__.D'>, <class '__main__.A'>, <class '__main__.B'>, <class '__main__.C'>, <class 'object'>]

    18,钻石继承问题:

    class A:
        def func(self):print('A')
    class B(A):
        def func(self):print('B')
    class C(A):
        def func(self): print('C')
    
    class D(B,C):
        def func(self): print('D')
    
    
    # 调用顺序
    print(D.mro())
    # [<class '__main__.D'>, <class '__main__.B'>, <class '__main__.C'>, <class '__main__.A'>, <class 'object'>]

    19,Python3里面所有的新式类都是采用广度优先的方式,漏斗,如果后面有机会找到爷爷类,那么就可以广度优先找

    # 漏斗
    class A:
        def func(self):print('A')
    class B(A):
        def func(self):print('B')
    class E:
        def func(self):print('E')
    class C(E):
        def func(self): print('C')
    
    class D(B,C):
        def func(self): print('D')
    
    
    # 调用顺序
    print(D.mro())
    # [<class '__main__.D'>, <class '__main__.B'>, <class '__main__.A'>, <class '__main__.C'>, <class '__main__.E'>, <class 'object'>]

    20,小乌龟问题,就是一个六边形,

    # 小乌龟
    class F:
        def func(self):print('F')
    
    class A(F):
        def func(self):print('A')
    class B(A):
        def func(self):print('B')
    class E(F):
        def func(self):print('E')
    class C(E):
        def func(self): print('C')
    
    class D(B,C):
        def func(self): print('D')
    
    
    # 调用顺序
    print(D.mro())
    # [<class '__main__.D'>, <class '__main__.B'>, <class '__main__.A'>, <class '__main__.C'>, <class '__main__.E'>, <class '__main__.F'>, <class 'object'>]

    21,get 一个算法,method resolution order mro,新式类,广度优先;经典类是深度优先(一条道走到黑,只要能到就一直走这条道,走到头就走另外一条),继承object的类才是新式类,经典类如果直接创建一个类在2.7中就是经典类,深度优先。

    22,多继承中,我们子类的对象调用一个方法,默认是就近原则,经典类中,深度优先,新式类中,广度优先,python2.7新式类和经典类共存,新式类要继承object,python3中只有新式类,默认继承object,经典类和新式类有一个区别super,mro方法只在新式类中存在

    23,super的本质,单继承里面永远是父类,只有多继承才会出现同级的super。

    class A:
        def func(self):print('A')
    
    
    class B(A):
    
        def func(self):
            super().func()
            print('B')
    
    class C(A):
    
        def func(self):
            super().func()
            print('C')
    
    class D(B,C):
    
        def func(self):
            super().func()
            print('D')
    
    d = D()
    d.func()
    
    print(D.mro())  # [<class '__main__.D'>, <class '__main__.B'>, <class '__main__.C'>, <class '__main__.A'>, <class 'object'>]
    
    # A
    # C
    # B
    # D
    
    # super的本质,不是直接找父类,而是根据调用者的节点位置的广度优先顺序来的
  • 相关阅读:
    Min25 筛与 Powerful Numbers
    「CF576D」 Flights for Regular Customers
    「CF568C」 New Language
    「CF559E」 Gerald and Path
    「CF555E」 Case of Computer Network
    20210604
    20210603模拟赛总结
    20210602模拟赛总结
    CF603E 整体二分
    20210601模拟赛总结
  • 原文地址:https://www.cnblogs.com/lisa-blog/p/10228875.html
Copyright © 2011-2022 走看看