zoukankan      html  css  js  c++  java
  • 继承:单继承与多继承/新式类的广度优先查询/经典类的深度优先查询

    本节主要内容:

    1.继承

    2.新式类与经典类

    3.多继承的优先查询

    一.继承

    定义一个类,class Dog(Animal)  其中括号里面的Animal是父类/基类/超类,括号外面的Dog是子类/派生类.

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

    当我们在定义多个类的时候,发现要用到相同的方法或变量,如果每个类都要写相同的方法和变量,那么代码就会重复,为了减少代码,可以用继承来解决.

    # encoding:utf-8
    # 如果是用的python2,python2默认使用ascii码,先再第一行写上encoding:utf-8 ;
    # python3默认使用的是utf-8

    组合:让一个类对象与另一个类的对象发生关系
    继承:让类与类发生关系

    面向对象的三大特性: 继承 多态 封装
    面向对象为什么要有继承?继承的好处是什么?
    a, 提高了代码的复用性
    b:提高了代码的维护性
    c:让类与类之间产生了关系,是多态的前提
    # 子类以及子类实例化的对象 可以访问父类的任何方法或变量.
    # 类名可以访问父类所有内容
    # 子类实例化的对象也可以访问父类所有内容
    # 父类不能访问子类的东西
    
    
    #这几个类用到了相同的方法和变量,为了提高代码的复用性,引入继承的思想
    class Animal:
        def __init__(self,name,sex,age):
            self.name = name
            self.sex = sex
            self.age = age
    
    class Person:
        def __init__(self,name,sex,age):
            self.name = name
            self.sex = sex
            self.age = age
    
    class Cat:
        def __init__(self,name,sex,age):
            self.name = name
            self.sex = sex
            self.age = age
    
    class Dog:
        def __init__(self,name,sex,age):
            self.name = name
            self.sex = sex
            self.age = age
    
    
    class Animal:
        breath = '呼吸'
    
        def __init__(self, name, sex, age):
            self.name = name
            self.sex = sex
            self.age = age
    
        def eat(self):
            print(self)
            print('动物都需要进食....')
    
    
    class Person(Animal):  # 括号里面的 父类,基类,超类   括号外面的 子类,派生类.
        pass
    
    
    class Cat:
        pass
    
    
    class Dog:
        pass
    
    
    p1 = Person('alex', 'laddyboy', 1000)
    print(p1.__dict__)  #{'name': 'alex', 'sex': 'laddyboy', 'age': 1000}
    
    # 初识继承:
    # 子类以及子类实例化的对象 可以访问父类的任何方法或变量.
    # 类名可以访问父类所有内容
    print(Person.breath)   #呼吸
    Person.eat(111)   #111
                      #动物都需要进食....
    # 子类实例化的对象也可以访问父类所有内容
    print(p1.breath)  #呼吸
    print(p1)     #<__main__.Person object at 0x0000006ECD9A7C88>
    p1.eat()    #<__main__.Person object at 0x0000006ECD9A7C88>
                #动物都需要进食....

    查询顺序:子类的对象空间==>子类空间==>父类空间

    只执行父类的方法:子类中不要定义与父类同名的方法
    只执行子类的方法:在子类创建这个方法.

    既要执行子类的方法,又要执行父类的方法?
    有两种解决方法.
    1,Animal.__init__(self, 参数)
    2,super().__init__(参数)
    class Animal:
        def __init__(self,name):
            self.name=name
    
        # def eat(self):
        #     print("会")
    
        def eat(self):
            print("%s会吃" %self.name)
    
        def drink(self):
            print("%s会喝" %self.name)
    
    class Cat(Animal):
        def tian_zhua_zi(self):
            print("%s会舔爪子" %self.name)
    
    class Dog(Animal):
        def kan_jia(self):
            print("%s会看家" %self.name)
    
    class Chicken(Animal):
        def xia_dan(self):
            print("%s会下蛋" %self.name)
    
    
    class Bird(Animal):
        def __init__(self,name,wing):     #self=Bird的实例化对象b,  name="鹦鹉",  wing="绿翅膀"
            #Animal.__init__(self,name)    #类名.函数+(),,相当于函数的调用,()里面装的是实参,把self,name当做实参传进来
                         # (self现在是指Bird的对象b,也就是个空间地址),然后执行函数,父类的函数对name进行封装,函数执行完毕,
                         # 执行下一步,self.wing=wing,是Bird自身对对象的属性进行封装.
            super().__init__(name)#super(Bird,self).__init__(name)  用super()直接把想要的父类的参数拿过来,然后封装自己的参数
            self.wing=wing
            print(name,wing)
    
        def eat(self):
            super().eat()
            print("%s会吃小虫子" % self.name)
    
    
    # c=Cat()     #父类中没有__init__方法,实例化一个子类的对象,子类的对象调用父类的方法,也会执行父类方法中的内容
    # c.eat()
    
    # c=Cat("猫")
    # c.eat()
    # c.drink()
    # c.tian_zhua_zi()
    #
    # d=Dog("狗")
    # d.eat()
    # d.drink()
    # d.kan_jia()
    #
    # j=Chicken("鸡")
    # j.eat()
    # j.drink()
    # j.xia_dan()

    二.新式类与经典类


    继承: 单继承,多继承.

      单继承:只继承一个父类
       class A(B):
      pass
    多继承:继承两个及两个以上的父类
       class A(B,C):
       pass
      
    : 经典类, 新式类

    新式类: 凡是继承object类都是新式类.
       python3x 所有的类都是新式类,因为python3x中的类都默认继承object.

    经典类: 不继承object类都是经典类
       python2x:(既有新式类,又有经典类) 所有的类默认都不继承object类,所有的类默认都是经典类.你可以让其继承object.


    三.多继承的优先查询

    1.单继承: 新式类,经典类查询顺序一样.
    2.多继承:
    新式类: 遵循广度优先.
    经典类: 遵循深度优先.

    3.多继承的新式类
      
    广度优先
    : 一条路走到倒数第二级,判断,如果其他路能走到终点,则返回走另一条路.如果不能,则走到终点.

    4.多继承的经典类  

    深度优先 : 一条路走到底.

    5.查询类的继承顺序: 类名.mro()

    class A:
        def func(self):
            print('IN A')
    
    class B(A):
        pass
        # def func(self):
        #     print('IN B')
    
    class C(A):
        pass
        # def func(self):
        #     print('IN C')
    
    class D(B):
        pass
        # def func(self):
        #     print('IN D')
    
    class E(C):
        pass
        # def func(self):
        #     print('IN E')
    
    class F(D,E):
        pass
        # def func(self):
        #     print('IN F')
    
    f1 = F()
    print(F.mro())
    #[<class '__main__.F'>, <class '__main__.D'>, <class '__main__.B'>, <class '__main__.E'>, <class '__main__.C'>, <class '__main__.A'>, <class 'object'>]
    6.多继承广度优先查询算法
    #例子1

    class
    H: pass class G(H): pass class F(H): pass class E(G): pass class D(F): pass class C(E): pass class B(D): pass class A(B, C, D): pass print(A.mro()) ''' 首先找到A继承的三个类的深度继承顺序,放到一个列表中 B [B,D,F,H] C [C,E,G,H] D [D,F,H] 每个列表的第一个元素为头部,其它位置元素都为尾部,从第一个列表的头部开始找,找其他列表中尾部是否含有 这个类名,如果没有,提取出来放到一个列表中,如果有,找下一个列表的头部,循环下去 只要提取来一个,我们就从第一个列表的头部接着重复上面的操作. A [A] [B,D,F,H] [C,E,G,H] [D,F,H] [B,C,D] A #找到第一个列表的头A,其他列表尾部没有A,把A取出来,如果其他列表的头部有A则剔除 [] [B,D,F,H] [C,E,G,H] [D,F,H] [B,C,D] B [] [D,F,H] [C,E,G,H] [D,F,H] [C,D] C [] [D,F,H] [E,G,H] [D,F,H] [D] D [] [F,H] [E,G,H] [F,H] [] F [] [H] [E,G,H] [H] [] E #找到第一个列表的头部H,但是其他列表尾部有H,所以跳过这个列表,去下一个列表取头部 [] [H] [G,H] [H] [] G [] [H] [H] [H] [] H [] [] [] [] [] lst = [A,B,C,D,F,E,G,H] '''
    #例子2

    class
    F: pass class E: pass class D: pass class C(D, F): pass class B(E, D): pass class A(B, C): pass print(A.mro()) ''' 首先找到A继承的两个类的深度继承顺序 把B作为子类,找出B类的查询顺序 B [B] [E] [D] [E,D] B [] [E] [D] [E,D] E [] [] [D] [D] D [] [] [] []
    lst = [B,E,D] 把C作为子类,找出C类的查询顺序 C [C] [D] [F] [D,F] C [] [D] [F] [D,F] D [] [] [F] [F] F [] [] [] [] lst = [C,D,F] A [A] [B,E,D] [C,D,F] [B,C] A [] [B,E,D] [C,D,F] [B,C] B [] [E,D] [C,D,F] [C] E [] [D] [C,D,F] [C] C [] [D] [D,F] [] D [] [] [F] [] F [] [] [] [] lSt = [A,B,E,C,D,F]
    '''
     
  • 相关阅读:
    [Python学习之路] 猜大小游戏
    C语言学生成绩管理系统(简易版)
    malloc动态分配字符串数组“ 一个月内的提醒”
    结构体指针排序
    C语言结构体排序
    数据测压,数据库查询,修改,添加
    badboy脚本录制
    性能测试
    JDK开发环境搭建及环境变量配置(win10)Jmeter之安装和配置
    Charles 修改返回值response(方法 breakpoints)
  • 原文地址:https://www.cnblogs.com/mwj-blog1/p/9389535.html
Copyright © 2011-2022 走看看