zoukankan      html  css  js  c++  java
  • python学习第16天----继承、查找顺序(深度、广度优先)

    面向对象的三大特性:继承、封装、多态

    1.继承

    1)定义:子类以及子类实例化的对象,可以访问父类的任何方法和变量;类名括号中的类名为父类,也叫基类,超类;括号外面的类为字类,也叫派生类

    2)优点:

    ①节省代码

    ②规范代码

    #通过子类的类名可以访问父类的所有内容

    class Animal:
        def __init__(self,name,age,sex):
            self.name = name
            self.age = age
            self.sex = sex
        def eat(self):
            print("动物都能吃东西。。。")
    class Person(Animal):
        pass
    
    Person.eat(11)
    Person.name = "阿狸"
    print(Person.name)
    print(Person.breath)
    输出:
    动物都能吃东西。。。
    阿狸
    呼吸
    View Code

    #子类实例化的所有对象也可以访问父类的所有内容

    class Animal:
        breath = "呼吸"
        def __init__(self,name,age,sex):
            self.name = name
            self.age = age
            self.sex = sex
        def eat(self):
            print("动物都能吃东西。。。")
    class Person(Animal):
        pass
    
    p = Person("阿狸",18,"")
    p.eat()
    print(p.breath)
    输出:
    动物都能吃东西。。。
    呼吸
    View Code

    变量、方法查询顺序:先从本类中查询,如果没有,再从父类中查询

    例:写三个类:狗、猫、鸡,每个类中都有吃、喝、自己的方法,最后定义一个Animal类

    class Animal:
        def __init__(self,name,age,sex):
            self.name = name
            self.age = age
            self.sex = sex
        def eat(self):
            print("%s吃东西" % self.name)
        def dring(self):
            print("%s喝东西" %self.name)
    
    class Cat(Animal):
        def bark(self):
            print("喵喵喵")
    class Dog(Animal):
        def bark(self):
            print("汪汪汪")
    class Chook(Animal):
        def bark(self):
            print("咕咕咕")
    c1 = Cat("Tom",3,"")
    c1.eat()
    c1.dring()
    c1.bark()
    d1 = Dog("豆豆",5,"")
    d1.eat()
    d1.bark()
    输出:
    Tom吃东西
    Tom喝东西
    喵喵喵
    豆豆吃东西
    汪汪汪
    View Code

    总结:

             ①若只执行父类的方法:在子类中不要定义与父类同名的方法

             ②只执行子类的方法:在子类中创建这个方法

             ③即执行本类方法,又执行父类的方法【父类名.方法名(参数)】【super().方法名(参数)】

    3)若既要执行子类的方法,又要执行父类的方法(两种方式)

    ①则需要在子类中__init__方法中调用父类的__init__方法,然后再添加子类自己的属性

    class Animal:
        def __init__(self,name,age,sex):
            self.name = name
            self.age = age
            self.sex = sex
        def eat(self):
            print("%s吃东西" % self.name)
        def dring(self):
            print("%s喝东西" %self.name)
    class Bird(Animal):
        def __init__(self,name,age,sex,wing):
            Animal.__init__(self,name,age,sex)
            self.wing = wing
    class Cat(Animal):
        def bark(self):
            print("喵喵喵")
    
    b1 = Bird("鹦鹉",10,"","绿翅膀")
    print(b1.__dict__)
    输出:
    {'age': 10, 'name': '鹦鹉', 'wing': '绿翅膀', 'sex': ''}
    View Code

    ②利用super关键字,起到的功效和法一一模一样,只是写法不一样

    super(本类类名,本类实例化对象).父类的__init__(参数)方法;可把本类类名和本类实例化对象去掉

    class Animal:
        def __init__(self,name,age,sex):
            self.name = name
            self.age = age
            self.sex = sex
        def eat(self):
            print("%s吃东西" % self.name)
        def dring(self):
            print("%s喝东西" %self.name)
    class Bird(Animal):
        def __init__(self,name,age,sex,wing):
            #Animal.__init__(self,name,age,sex)
            super(Bird,self).__init__(name,age,sex)
            #super().__init__(name,age,sex)                #写一种即可
            self.wing = wing
    class Cat(Animal):
        def bark(self):
            print("喵喵喵")
    
    b1 = Bird("鹦鹉",10,"","绿翅膀")
    print(b1.__dict__)
    输出:
    {'sex': '', 'age': 10, 'wing': '绿翅膀', 'name': '鹦鹉'}
    View Code

    例:实现既要执行本类的方法,又要执行父类的方法;如动物吃肉,猫吃肉同时还要吃鱼

    class Animal:
        def __init__(self,name,age,sex):
            self.name = name
            self.age = age
            self.sex = sex
        def eat(self,argv):
            print("%s吃%s" % (self.name,argv))
        def dring(self):
            print("%s喝东西" %self.name)
    
    class Cat(Animal):
        def bark(self):
            print("喵喵喵")
        def eat(self,argv):
            super().eat(argv)
            print("猫吃鱼")
    
    c1 = Cat("Tom",3,"")
    c1.eat("")
    输出:
    Tom吃肉
    猫吃鱼
    View Code

    3)补充:继承和类的分类

    ①继承继承分为单继承和多继承

    ②类分为经典类和新式类

    1'新式类:凡是继承object类都是新式类;在python3.x中,所有的类都是新式类,所有类默认继承object类;

    2'经典类:不继承object类都是经典类;python2.x中既有新式类,又有经典类,所有的类都默认不继承object类,所有的类默认都是经典类,但可以手动让其继承object类,成为新式类

    4)查询顺序区别

    ①在单继承中,新式类和经典类的查询顺序一样

    ②在多继承中,新式类查询遵循广度优先;经典类查询遵循深度优先

    #多继承的新式类:广度优先

    class A:
        def func(self):
            print('IN A')
    
    class B(A):
        def func(self):
            print('IN B')
    
    class C(A):
        def func(self):
            print('IN C')
    
    class D(B):
        def func(self):
            print('IN D')
    
    class E(C):
        def func(self):
            print('IN E')
    
    class F(D,E):
        def func(self):
            print('IN F')
    
    f1 = F()
    f1.func()
    View Code

    广度优先查询顺序

    总结:广度优先,即每个节点有且只走一次(先沿着第一条路走,然后判断最后的基类是否还有其他路可以到达,如果还有其他路可以达到基类,就不再沿着当前路走)

    #若代码中类过多,无法判断类的继承顺序,可使用方法mro()查看类的继承顺序,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()
    f1.func()
    print(F.mro())   #打印类的继承顺序
    输出:
    IN F
    [<class '__main__.F'>, <class '__main__.D'>, <class '__main__.B'>, <class '__main__.E'>, <class '__main__.C'>, <class '__main__.A'>, <class 'object'>]
    View Code

    #多继承的经典类:深度优先(py3无法测试,需要py2)

             对于深度优先,类的查询顺序是一条路走到底(即第一条路全部查询完,如果再找不到,才会走第二条路)

    class A:
        def func(self):
            print('IN A')
    
    class B(A):
        def func(self):
            print('IN B')
    
    class C(A):
        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()
    f1.func()
    查询顺序为:D----B-----A-----E------C
    View Code

    注:对于此处的深度优先和广度优先的顺序,只能是继承两个类的情况,继承两个以上的类,顺序会出现问题

    2.练习

    1.通过具体代码完成如下要求

    1)定义一个父类Animal,在构造方法中封装三个属性,姓名,性别,年龄,再给其添加一个eat的方法,方法中显示%s正在吃饭(%s是哪个对象调用此方法,显示哪个对象名字)。
    2)定义两个子类Person,Dog,全部继承这个父类Animal.
    3)Person类中,有构造方法,封装一个皮肤的属性,有eat方法,方法中显示人类正在吃饭。
    4)Dog类中,有构造方法,封装一个毛色的属性,有eat方法,方法中显示狗狗正在吃饭。
    上面这几个类创建完成之后,完成下列要求:
    ①: 实例化一个人类的对象,让其只封装皮肤属性。

    class Animal:
        def __init__(self,name,sex,age):
            self.name = name
            self.sex = sex
            self.age = age
        def eat(self):
            print("%s正在吃饭" % self.name)
    class Person(Animal):
        def __init__(self,skin):
            self.skin = skin
        def eat(self):
            print("人类正在吃饭")
    class Dog(Animal):
        def __init_self(self,hair_color):
            self.hair_color = hair_color
        def eat(self):
            print("狗狗正在在吃饭")
    #实例化一个人类的对象,让其只封装皮肤属性。
    p1 = Person("黄皮肤")
    print(p1.__dict__)
    输出:
    {'skin': '黄皮肤'}
    View Code

    ②: 实例化一个人类的对象,让其封装姓名,性别,年龄,皮肤四个属性。

    class Animal:
        def __init__(self,name,sex,age):
            self.name = name
            self.sex = sex
            self.age = age
        def eat(self):
            print("%s正在吃饭" % self.name)
    class Person(Animal):
        def __init__(self,name,sex,age,skin):
            super().__init__(name,sex,age)
            self.skin = skin
        def eat(self):
            print("人类正在吃饭")
    class Dog(Animal):
        def __init_self(self,hair_color):
            self.hair_color = hair_color
        def eat(self):
            print("狗狗正在在吃饭")
    
    #实例化一个人类的对象,让其封装姓名,性别,年龄,皮肤四个属性。
    p2 = Person("","",18,"黄皮肤")
    print(p2.__dict__)
    输出:
    {'name': '', 'skin': '黄皮肤', 'sex': '', 'age': 18}
    View Code

    ③: 实例化一个狗类的对象,让其只封装毛色属性。

    class Animal:
        def __init__(self,name,sex,age):
            self.name = name
            self.sex = sex
            self.age = age
        def eat(self):
            print("%s正在吃饭" % self.name)
    class Person(Animal):
        def __init__(self,name,sex,age,skin):
            super().__init__(name,sex,age)
            self.skin = skin
        def eat(self):
            print("人类正在吃饭")
    class Dog(Animal):
        def __init__(self,hair_color):
            self.hair_color = hair_color
        def eat(self):
            print("狗狗正在在吃饭")
    
    d1 = Dog("黑毛")
    print(d1.__dict__)
    输出:
    {'hair_color': '黑毛'}
    View Code

    ④: 实例化一个狗类的对象,让其封装姓名,性别,年龄,毛色四个属性。

    class Animal:
        def __init__(self,name,sex,age):
            self.name = name
            self.sex = sex
            self.age = age
        def eat(self):
            print("%s正在吃饭" % self.name)
    class Person(Animal):
        def __init__(self,name,sex,age,skin):
            super().__init__(name,sex,age)
            self.skin = skin
        def eat(self):
            print("人类正在吃饭")
    class Dog(Animal):
        def __init__(self,name,sex,age,hair_color):
            super().__init__(name,sex,age)
            self.hair_color = hair_color
        def eat(self):
            print("狗狗正在在吃饭")
    
    d2 = Dog("豆豆","",3,"黑毛")
    print(d2.__dict__)
    输出:
    {'sex': '', 'name': '豆豆', 'hair_color': '黑毛', 'age': 3}
    View Code

    ⑤: 实例化一个人类的对象,让其只执行父类的eat方法(可以对人类代码进行修改)。

    class Animal:
        def __init__(self,name,sex,age):
            self.name = name
            self.sex = sex
            self.age = age
        def eat(self):
            print("%s正在吃饭" % self.name)
    class Person(Animal):
        def __init__(self,name,sex,age,skin):
            super().__init__(name,sex,age)
            self.skin = skin
        # def eat(self):
        #     print("人类正在吃饭")
    class Dog(Animal):
        def __init__(self,name,sex,age,hair_color):
            super().__init__(name,sex,age)
            self.hair_color = hair_color
        def eat(self):
            print("狗狗正在在吃饭")
    
    p2 = Person("","",18,"黄皮肤")
    p2.eat()
    输出:
    劫正在吃饭
    View Code

    ⑥: 实例化一个狗类的对象,让其既执行父类的eat方法,又执行子类的eat方法。

    class Animal:
        def __init__(self,name,sex,age):
            self.name = name
            self.sex = sex
            self.age = age
        def eat(self):
            print("%s正在吃饭" % self.name)
    class Person(Animal):
        def __init__(self,name,sex,age,skin):
            super().__init__(name,sex,age)
            self.skin = skin
        # def eat(self):
        #     print("人类正在吃饭")
    class Dog(Animal):
        def __init__(self,name,sex,age,hair_color):
            super().__init__(name,sex,age)
            self.hair_color = hair_color
        def eat(self):
            super().eat()
            print("狗狗正在在吃饭")
    d2 = Dog("豆豆","",3,"黑毛")
    d2.eat()
    输出:
    豆豆正在吃饭
    狗狗正在在吃饭
    View Code

    2.写出下列代码的执行结果

    class Parent:
        def func(self):
            print('in Parent func')
    
        def __init__(self):
            self.func()      #此处的self还是子类对象,所以执行子类的func
    
    class Son(Parent):
        def func(self):
            print('in Son func')
    
    son1 = Son()
    输出:
    in Son func
    View Code

    3.判断如下程序输出:

    #对于类中变量是不可变的数据类,不能通过对象修改类变量,通过对象修改变量,只是修改本对象空间中的变量;

    class A:
        age = 10
    p1 = A()
    p2 = A()
    p1.age = 20
    p2.age = 30
    print(p1.age)
    print(p2.age)
    print(A.age)
    输出:
    20
    30
    10
    View Code

    #对于变量是可变的数据类型

    当程序运行看到的变量和值对应的关系存在全局名称空间中;如果这个变量对应的值是个可变的数据类型,这个名称空间存的是变量和这个可变数据类型(如列表)的内存地址

             对象.name是先从对象空间中查找name,若对象中没有,再从类中去找(即从类的名称空间中去找),即找到的是列表的内存地址

             通过对象给变量添加元素,就相当于往这个列表中添加了元素,而变量的内存地址不变

    class A:
        name = []
    p1 = A()
    p2 = A()
    p1.name.append(1)
    p2.name.append(2)
    print(p1.name)
    print(p2.name)
    输出:
    [1, 2]
    [1, 2]
    [1, 2]
    View Code
  • 相关阅读:
    apache httpd配置问题
    php文件上传进度控制模块
    “fixed” css style in mobile safari
    第八周进度表
    大白鱼团队项目计划表
    第七周进度表
    结对开发团队成员以及题目介绍
    软件工程结对作业01
    软件工程子数组求和1
    软件工程子数组求和2
  • 原文地址:https://www.cnblogs.com/piaolaipiaoqu/p/13877342.html
Copyright © 2011-2022 走看看