1.python继承的基本概念

  • 在程序中,继承描述的是多个类之间的所属关系。

  • 如果一个类A里面的属性和方法可以复用,则可以通过继承的方式,传递到类B里。

  • 那么类A就是基类,也叫做父类;类B就是派生类,也叫做子类。

  • 继承:描述的类与类之间所属关系。
    基本语法:
    class 类8(类A)
        pass
    称为类 B 继承A
    特点:B类的对象可以使用 A类的属性和方法
    优点:代码复用。重复相同的代码不用多次书写
    名词:
       类A:父类   基类
       类B:子类   派生类
    # 定义是个 动物类 animal类
    class Animal(object):
        # 在animal类书写play方法,输出快乐的玩耍
        def play(self):
            print('快乐的玩耍...')
            # 定义Dog类继承animal类
    
    
    class Dog(Animal):
        pass
    
    
    # 创建dog类对象,调用父类的方法
    dog = Dog()
    dog.play()

    2.继承分类:

    """

    单继承:如果一个类只有一个父类,把这种继承关系称为单继承

    多继承:如果一个类有多个父类,把这种继承关系称为多继承

    多层继承:c–>B–>A

    """

    # 定义是个 动物类 animal类
    class Animal(object):  # 对于Animal类和object类来说,单继承
        # 在animal类书写play方法,输出快乐的玩耍
        def play(self):
            print('快乐的玩耍...')
            # 定义Dog类继承animal类
    
    
    # 定义Dog类继承animal类
    class Dog(Animal):  # Dog-->Animal 也是单继承,Dog-->Animal-->object 这种继承关系称为多层继承
        def bark(self):
            print('汪汪叫......')
    
    
    # 定义类XTQ类,继承Dog类
    # 多层继承中,子类可以使用所有继承链中的类中的方法和属性
    class XTQ(Dog):  # XTQ--->Dog 单继承,XTQ--->Dog-->Animal 类,多层继承
        pass
    
    
    xtq = XTQ()
    xtq.bark()  # 调用父类Dog中的方法
    xtq.play()  # 调用爷爷类 animal类中的方法

    3.子类重写父类的同名方法(掌握)

    重写:子类定义和父类名字相同的方法
    为什么重写?
    解释:父类中的方法,不能满足子类对象的需求,所以要重写。
    重写之后特点:子类对象调用子类自己的方法,不在调用的方法,父类对象调用父类自己的方法
    # 1.定义Dog类,书写bark方法,输出 汪汪汪叫
    class Dog(object):
        def bark(self):
            print('汪汪汪叫')
    
    
    # 2.定义XTQ类,重写父类中的方法,输出 嗷嗷嗷叫
    class XTQ(Dog):
        def bark(self):
            print('嗷嗷嗷叫')
    
    
    # 创建Dog类对象
    dog = Dog()
    dog.bark()  # 父类自己
    # 创建XTQ类对象
    xtq = XTQ()
    xtq.bark()  

    4.子类调用父类中的同名方法

    在代码中解释

    # 1.定义Dog类,书写bark方法,输出 汪汪汪叫
    class Dog(object):
        def bark(self):
            print('汪汪汪叫')
    
    
    # 2.定义XTQ类,重写父类中的方法,输出 嗷嗷嗷叫
    class XTQ(Dog):
        def bark(self):
            print('嗷嗷嗷叫')
    
        def see_host(self):
            """看见主人在之后,要汪汪叫,不能嗷嗷嗷叫"""
            print('看见主人了,', end='')
            # self.bark()
            # 想要在子类中调用父类的同名方法
            # 方法一:父类名.方法名(self,其他参数),通过实例对象.方法名()调用方法,不需要给self传递实参值,
            # python解释器会自动将对象作为实参值传递给self形参,如果是通过类名.方法()调用,python解释器就
            # 不会自动传递实参值,需要手动给self形参传递实参值
            Dog.bark(self)
            # 父类名(实参).方法名
            # 方法二: supper(类A,self).方法名(参数名),会调用当类A的父类中的方法
            super(XTQ, self).bark()  # 调用XTQ类父类中的bark方法
            # 方法三:是方法二的简写:super().方法名(参数)--等价于--super(当前类,self).方法名
            super().bark()
    
    
    # 创建XTQ类对象
    xtq = XTQ()
    xtq.see_host()

    5.继承中的init(掌握)

    # 1.定义Dog类
    class Dog(object):
        def __init__(self, name):
            # 添加属性
            self.age = 0
            self.name = name
    
        def __str__(self):
            return f'小狗名字{self.name},小狗年龄{self.age}'
    
    
    # 2.定义XTQ类继承Dog类
    class XTQ(Dog):
        # 子类重写了父类的__init__方法,默认不在调用父类的init方法,需要手动的调用父类的init方法
        def __init__(self, name, color):
            super().__init__(name)  #调用父类中的形参
            self.color = color   #调用自己独有的形参
    
        def __str__(self):
            return f'小狗名字{self.name},小狗年龄{self.age},该颜色为{self.color}'
    
    
    # 3.创建XTQ类对象
    xtq = XTQ('小黄', '红色')
    print(xtq)

    注意:1.如果子类重写了父类的init方法,在子类中需要调用父类的init方法,给对象添加从父类继承的属性

    1. 子类init方法的形参,一般都先写父类的形参,在写自己独有的形参

    6.多继承(理解)

    如果一个类有两个及以上的父类,就把这种继承关系称为多继承

    代码进行解释

    # ---多继承---
    # 1.定义Dog类,定义bark方法,和eat方法
    # 2.定义God类,定义play方法和eat方法
    # 3.定义XTQ类,继承Dog类和God类
    class Dog(object):
        def bark(self):
            print('汪汪叫...')
    
        def eat(self):
            print('啃骨头')
    
    
    class God(object):
        def play(self):
            print('在云中漂移一会')
    
        def eat(self):
            print('吃蟠桃')
    
    
    class XTQ(God, Dog):  # XTQ类有两个父类,这个继承关系称为多继承,XTQ类对象,可以调用两个父类中的属性和方法
        pass
    
    
    # 4.创建XTQ类对象
    xtq = XTQ()
    xtq.bark()  # 调用Dog父类中的方法
    xtq.play()  # 调用God父类中的方法
    xtq.eat()  # 两个父类都存在eat方法,子类对象调用的是 第一个父类中的方法

    7.多继承中调用指定父类中的方法

    # ---多继承指定父类中的方法---
    # 1.定义Dog类,定义bark方法,和eat方法
    # 2.定义God类,定义play方法和eat方法
    # 3.定义XTQ类,继承Dog类和God类
    class Dog(object):
        def bark(self):
            print('汪汪叫...')
    
        def eat(self):
            print('啃骨头')
    
    
    class God(object):
        def play(self):
            print('在云中漂移一会')
    
        def eat(self):
            print('吃蟠桃')
            # 调用指定父类中的方法
            # 方法一:
    
    
    class XTQ(God, Dog):  # XTQ类有两个父类,这个继承关系称为多继承,XTQ类对象,可以调用两个父类中的属性和方法
        def eat(self):
            print('子类重写eat方法,调用子类自己的方法')
            # 调用指定父类中的方法
            # 方法一:类名.方法名(self,参数)
            Dog.eat(self)---重点
            # 方法二:supet(类A,self).方法名(参数) 类A的父类(继承顺序链的下一个类)中的方法
            # super(XTQ, self).eat()  # God类中的方法
            # super(God, self).eat()  # 调用的Dog类中的方法
            # super(Dog, self).eat()  # 调用的object类中的方法,注意:object类中没有eat方法,代码报错
    
    
    # 4.创建XTQ类对象
    xtq = XTQ()
    xtq.bark()  # 调用Dog父类中的方法
    xtq.play()  # 调用God父类中的方法
    xtq.eat()  # 两个父类都存在eat方法,子类对象调用的是 第一个父类中的方法
    
    # 类名__mro__可以当前类的继承顺序链,也叫做方法的调用顺序
    print(XTQ.__mro__)

    8.私有权限

    1. 面对对象三大特性:封装,继承,多态

    1. 封装的意义:

  • 将属性和方法放到一起作为一个整体,然后通过实例化对象来处理;

  • 隐藏内部实现细节,值需要和对象及其属性和方法交互就可以了;

  • 对类的属性和方法增加 访问权限。

  • 私有权限:在属性名和方法名 前面 加上两个下划线__

    1.类的私有属性和私有方法,都不能通过对象直接访问,但是可以在本类内部访问;

    2.类的私有属性和私有方法,都不会被子类继承,子类也无法访问;

    3.私有属性和私有方法 往往用来处理类的内部事情,不通过对象处理,起到安全作用。

    访问权限控制:在什么地方可以使用和操作
    私有权限:
       定义;在方法和属性前加上两个下划线,就变为私有。
       1.不能在类外部通过对象直接访问和使用,只能在类内部访问和使用
       2.不能被子类继承
    公有:不是私有的,就是公有的。
    """
    私有属性,只需要在原属性名前加上两个下划线,即可
    目的:保证数据的相对安全,
    想要访问和使用私有属性:定义一个公有的方法,通过这个方法使用
    """
    
    
    # 案例需求:
    # 1.定义People类,定义属性ICBC_money,钱不能随便修改,必须是合法的终端才可以操作
    class People(object):
        def __init__(self):
            # python中的私有本质是 修改属性的名字,在创建对象的时候,会自动的修改属性名
            # 在属性名的前边加上_类名前缀
            self.__ICBC_money = 0  # 私有属性
    
        # 定义共有方法,提供接口,修改余额
        def get_money(self):
            return self.__ICBC_money
    
        def set_money(self, money):
            self.__ICBC_money += money
    
    
    # 创建People类对象
    
    
    xw = People()
    # 实例对象.__dict__ 可以查看对象具有的属性信息,类型是字典,字典的key是属性名,字典的value是属性值
    print('赋值之前:', xw.__dict__)
    xw.__ICBC_money = 1000  # 不是修改私有属性,是重新添加一个共有属性
    print('复制之后:', xw.__dict__)
    
    print(xw.get_money())
    xw.set_money(1000)
    print(xw.get_money())
    xw.set_money(-500)
    print(xw.get_money())

    8.私有方法

    """
    私有方法:在方法的前边加上两个__,就为私有方法
    私有方法,不能在类外部访问
    作用:一般作为类内部的方法使用,不让外部调用的时候去定义,保证业务逻辑不被破坏
    """
    
    
    class Dog(object):
        def born(self):
            print('生了一个小狗')
            self.__sleep()
    
        def __sleep(self):
            print('休息30天')
    
    
    dog = Dog()
    # dog.__sleep()
    dog.born()

    9.类属性

    # ---类属性---
    """
    对象(实例对象):通过class定义的类创建的,即通过类实例化来的,又称为实例,实例对象
    实例对象定义的属性称为是 实例属性,通过实例对象(self)定义的属性都是实例属性
    实例属性:每个实例对象中都存在一份,并且只可能不一样的
    
    类(类对象):通过class定义的,又称为类对象,是python解释器在创建类的时候自动创建的
    作用:1.通过类对象,去定义实例对象
    2.类对象可以保存一些属性信息,称为类属性
    类属性的定义:在类内部,方法外部定义的变量就是类属性
    类属性,字内存中只有一份
    
    如何确定一个属性是该定义为实例属性还是类属性?
    先假设这个属性为实例属性,查看
    """
    
    
    class Dog(object):
        # 定义类属性,类名
        class_name = '狗类'
    
        def __init__(self, name, age):
            # 定义的都是实例属性
            self.name = name
            self.age = age
    
    
    # 创建Dog 类对象
    dog = Dog('小白', 3)
    print(dog.__dict__)  # 打印dog对象具有的属性
    # 类名.__dict__查看类对象具有的属性
    print(Dog.__dict__)
    # 访问类属性
    # 类名.类属性
    print(Dog.class_name)
    # 修改类属性  类名.类属性=属性值
    Dog.class_name = 'Dog类'
    print(Dog.class_name)
    # 补充  注意:如果不存在和实例属性名相同的类属性,则可以使用实例对象访问类属性的值
    # 如果存在重名,则使用实例属性访问的一定是实例属性,不是类属性

    10.类方法

    # ------------类方法-----
    """
    实例方法:类中默认定义的方法,就是实例方法,第一个参数为self,表示实例对象
    类方法:使用@cclassmethod 装饰的方法,称为类方法,第一个参数是cls,代表的是类对象自己
    什么情况定义为实例方法,什么情况定义为类方法?
    1.如果在方法中使用了实例属性,那么该方法必须定义为实例方法
    2.前提:不需要使用实例属性,需要使用类属性,可以将这个方法定义类方法
    """
    
    
    class Dog(object):
        class_name = '狗类'
    
        def __init__(self, name, age):
            self.name = name
            self.age = age
    
        def play(self):
            print(f'小狗{self.name}快乐中方法......')
    
        # def get_class_name(self):
        #     return Dog.class_name  # 是实例方法,因为没有使用实例属性,所以可以定义为类方法
        @classmethod
        def get_class_name(cls):
            return cls.class_name  # cls是类方法的默认形参,在调用的时候,不需要手动传递,python解释器会自动传递
    
    
    dog = Dog('大黄', 3)
    dog.play()
    print(dog.get_class_name())  # 对象.类方法()
    # 类名.类方法()
    print(Dog.get_class_name())

    11.静态方法

    # ------------------静态方法------------
    
    # 静态方法:使用@staticmethod 装饰的方法,称为静态方法,对参数没有特殊要求,可以有,可以没有
    # 什么情况定义下静态方法:
    # 前提:不需要使用实例属性,同时也不需要使用类属性,此时可以将这个方法定义为静态方法
    class Dog(object):
        class_name = '狗类'
    
        def __init__(self, name, age):
            self.name = name
            self.age = age
    
        def play(self):
            print(f'小狗{self.name}快乐中方法......')
    
        @staticmethod  # 定义静态方法
        def show_into():   #静态方法如果有参数,就必须传递实参值
            print('这是Dog类')
    
    
    dog = Dog('大黄', 2)
    dog.play()
    # 对象.方法名()
    dog.show_into()
    # 类名.方法名
    Dog.show_into()

    12.多态方法

    在需要使用父类对象的地方,也可以使用子类对象,这种情况就叫多态。

    比如:在函数中,我需要调用 某一个父类对象的方法,那么我们也可以在这个地方调用子类对象的方法

    如何在程序中使用多态

    可以按照以下几个步骤来写代码:
    1.子类继承父类
    2.子类重写父类中的方法
    3.通过对象调用这个方法
    """
    在需要使用父类对象的地方,也可以传入子类对象,得到不同的结果....多态
    实现步骤:
    1.子类继承父类
    2.子类重写父类中的同名方法
    3.定义一个共同的方法,参数为父类对象。在方法中调用子类和父类同名的方法
    """
    
    
    # 1.定义Dog类
    class Dog(object):
        def __init__(self, name):
            self.name = name
    
        def play(self):
            print(f'小狗{self.name}在玩耍...')
    
    
    # 2.定义哮天犬类,继承Dog类
    class XTQ(Dog):
        # 3.重写play方法
        def play(self):
            print(f'{self.name}追天上云彩')
    
    
    # 4.定义一个共同的方法,
    def play_with_dog(obj_dog):
        obj_dog.play()
    
    
    # 创建Dog类对象
    dog = Dog('大黄')
    play_with_dog(dog)
    
    # 创建一个XTQ类的对象
    xtq = XTQ('小黑')
    play_with_dog(xtq)

    11.鸭子类型中的多态(不是重点)

    鸭子类型多态:可以没有继承
    # 1.定义Dog类
    class Dog(object):
        def __init__(self, name):
            self.name = name
    
        def play(self):
            print(f'小狗{self.name}在玩耍...')
    
    
    # 2.定义哮天犬类,继承Dog类
    class XTQ(Dog):
        # 3.重写play方法
        def play(self):
            print(f'{self.name}追天上云彩')
    
    
    class Cat(object):
        def __init__(self, name):
            self.name = name
    
        def play(self):
            print(f'小猫{self.name}在快乐成长中...')  #这没有被继承
    
    
    # 4.定义一个共同的方法,
    def play_with_dog(obj_dog):
        obj_dog.play()
    
    
    # 创建Dog类对象
    dog = Dog('大黄')
    play_with_dog(dog)
    
    # 创建一个XTQ类的对象
    xtq = XTQ('小黑')
    play_with_dog(xtq)
    
    cat = Cat('小花')
    play_with_dog(cat)

    12.总结(思维导图)

    13.题型练习

    1.请写出单继承的格式?

    class 子类名(父类名)
          pass

    2.什么是重写,为什么要重写?

    1.重写:子类实现父类中的同名方法

    2.父类中的方法不能满足子类对象的需求

    3.如何将一个属性变为私有的?

    1.在属性名前加上两个下划线

    4.定义类方法的语法格式

    # 使用@classmethod 装饰的方法,是类方法
    class MyClass(object):
        @classmethod
        def func(cls):
            pass

    5.定义静态方法的语法格式?

    class MyClass(object):
        @staticmethod
        def func():
            pass

    6.请判断下面中哪些是类属性,哪些是实例属性?

    class Car(object):
        addr = 'china'
    
        def __init__(self):
            self.name = 'changcheng'
            self.money = 100000
    # addr 类属性
    # self.name 实例属性
    # self.money 实例属性

    7.判断题

    1.一个子类可以继承多个父类 #正确

    2.类中的方法可以有return,也可以没有return #正确

    3.类方法和静态方法是一样 # 错误

    4.删除对象时,默认调用__init__方法 # 错误,创建对象调用__init__方法,删除对象调用__del__方法

    5.python3中object是所有类的父类 #正确

    6.python中不支持多继承

    7.父类中的所有方法和属性都会被继承 # 错误 私有方法和属性不会继承

    8.重写方法后,父类对象默认调用重写后的方法 #错误,子类调用重写后的方法,父类调用父类自己的方法

    代码题(加强训练)

    (一).

    1. 创建一个Animals(动物)基类,其中有一个run方法,输出 跑起来…..

    1. 创建一个House(马) 类继承于动物类,Horse类中不仅有run方法还有eat方法

  • run方法输出 跑起来….

  • eat方法输出 吃东西….

  • class Animal(object):
        def run(self):
            print('跑起来....')
    
    
    class House(Animal):
        def eat(self):
            print('吃东西...')
    
    
    house = House()
    house.run()
    house.eat()

    (二).

    1. 创建一个Animals(动物)基类,其中有一个run方法,输出 跑起来…..

    1. 创建一个Horse(马)类继承于动物类,Horse类中重写run方法,增加打印输出'迈着矫健的步伐跑起来',同时实现eat方法,输出 吃东西…

    class Animals(object):
        def run(self):
            print('跑起来')
    
    
    class Horse(Animals):
        def run(self):
            Animals.run(self)  #方法二super(Horse,self).run()
            print('迈着矫健的步伐跑起来')
    
        def eat(self):
            print('吃东西...')
    
    
    house = Horse()
    house.run()
    house.eat()

    (三).

    1. 创建一个Animals(动物)基类,其中有一个run方法,输出 跑起来…..

    1. 创建一个Horse(马)类继承于动物类,Horse类中不仅有run方法还有eat方法

  • run方法输出 跑起来….

  • eat方法输出 吃东西….

  • 3.创建一个SwiftHorse(千里马)类继承Horse类,初始化init方法name属性为千里马

    class Animal(object):
        def run(self):
            print('跑起来....')
    
    
    class Horse(Animal):
        def eat(self):
            print('吃东西')
    
    
    class SwiftHorse(Horse):
        def __init__(self):
            self.name = '千里马'

    (四).

    1.创建一个Animals(动物)基类,其中有一个run方法,输出 跑起来…..

    2.创建一个Horse(马)类继承于动物类,Horse类中不仅有run方法还有eat方法

  • run方法输出 跑起来….

  • eat方法输出 吃东西….

  • 3.创建一个Donkey(驴)类继承于动物类,Donkey类中不仅有run方法还有eat方法

  • run方法输出 跑起来….

  • eat方法输出 驴吃东西….

    1. 创建一个Mule(骡子)类继承于House,Donkey,初始化name为骡子.

    问题:创建Mule类的对象,调用eat方法,调用的是哪个父类中的方法?—-Horse

    class Animal(object):
        def run(self):
            print('跑起来...')
    
    
    class Horse(Animal):
        def run(self):
            print('跑起来...')
    
        def eat(self):
            print('马吃东西')
    
    
    class Donkey(Animal):
        def run(self):
            print('跑起来...')
    
        def eat(self):
            print('驴吃东西')
    
    
    class Mule(Horse, Donkey):
        def __init__(self):
            self.name = '骡子'
    
    
    mule = Mule()
    mule.eat()

    (五).

    1. 创建一个动物类(Animal),其中有一个run方法

    1. 创建一个Cat类继承于动物类,具有私有属性__name='波斯猫'

    1. 创建一个Dog类继承于动物类,具有私有属性__name='京巴狗'

    1. Cat类中不仅有run方法还有eat方法

    1. Dog类中方法同上

    1. 创建一个letRun函数,可以接受动物及其子类对象,并调用run方法 class Cat(Animal):

    1. 编写测试代码以验证功能正常

    class Animal(object):
        def run(self):
            print('跑起来')
    
    
    class Cat(Animal):
        def __init__(self):
            self.__name = '波斯猫'
    
        def run(self):
            print(f'{self.__name}')
    
        def eat(self):
            print(f'{self.__name}')
    
    
    class Dog(Animal):
        def __init__(self):
            self.__name = '京巴狗'
    
        def run(self):
            print(f'{self.__name}')
    
        def eat(self):
            print(f'{self.__name}')
    
    
    # 创建一个letRun函数,可以接受动物及其子类对象,并调用run方法 class Cat(Animal):
    def LetRun(animal):
        animal.run()
    
    
    # 动物测试
    # 编写测试代码以验证功能正常
    animal = Animal()
    LetRun(animal)
    # 猫测试
    cat = Cat()
    LetRun(cat)
    cat.eat()
    # 狗测试
    dog = Dog()
    LetRun(dog)
    dog.eat()

    (六).—重点

    1. 定义一个Person类,包含初始化init方法:

    1. 实例属性:名字,name 年龄 ,age

  • 记录由该类创建的对象的个数,创建一个对象,计数+1,删除一个对象,计数减一

  • 定义一个方法,可以打印当前对象的个数

  • 定义一个方法show_info,输出以下信息

  • 这是Person类,谢谢查看

  • 打印对象的时候,可以输出打印自己的名字和年龄

  • 我的名字是…,年龄是…

  • 定义一个方法study,输出以下信息

  • 我叫…,我要好好学习

  • 操作方法

  • 1.调用show_info方法

    2.创建两个对象,打印当前对象,并打印当前的对象个数

    3.分别使用两个对象调用study方法

    4.删除一个对象,打印输出当前的对象个数

    class Person(object):
        __count = 0
    
        # 定义init方法,创建实例属性
        def __init__(self, name, age):
            self.name = name
            self.age = age
            Person.__count += 1
    
        # 定义类方法,打印当前对象个数
        @classmethod
        def get_count(cls):
            return cls.__count
    
        # 定义静态方法
        @staticmethod
        def show_info():
            print('这是Person类,谢谢查看')
    
        def __str__(self):
            return f'我的名字是{self.name},年龄是{self.age}'
    
        def study(self):
            print(f'我是{self.name},我要好好学习')
    
        def __del__(self):
            Person.__count -= 1
    
    
    Person.show_info()
    print(Person.get_count())
    person1 = Person('小王', 13)
    print(Person.get_count())
    person2 = Person('小红', 13)
    print(Person.get_count())
    person1.study()
    person2.study()
    del person1
    print(Person.get_count())
    物联沃分享整理
    物联沃-IOTWORD物联网 » Python中的继承详解

    发表评论