继承

本文详细介绍了Python中的继承概念,包括单继承、多层继承和多继承,以及如何调用父类方法。同时,讲解了类的权限,强调了私有属性和方法的使用限制。通过实例展示了如何在子类中重写和调用父类方法,以及如何访问私有成员。此外,还探讨了继承中的方法调用顺序和权限控制。
摘要由CSDN通过智能技术生成

1. 简介

  • 单继承:子类只继承一个父类
  • 多层继承:继承关系为多层传递,如生活中的爷爷、父亲、儿子

1.1 定义

1.1 生活中的继承
在现实生活中,继承一般指的是子女继承父辈的财产,如下图:
生活中继承
1.2 程序中的继承
在程序中,继承描述的是指的是类与类之间的关系,如下如所示:
程序中继承

  • 站在父类的角度来看,父类派生出子类
  • 站在子类的角度来看,子类继承于父类
  • 父类也叫基类,子类也叫派生类

1.2 作用

  • 继承:子类直接具备父类的能力(属性和方法)
  • 作用:解决代码重用问题,提高开发效率

1.3 语法格式

继承的语法格式:

class 子类名(父类名):
    pass

示例代码:

# 定义一个父类
class Father(object):
    # 添加一个属性, money
    def __init__(self):
        self.money = 9999999

    def print_info(self):
        print(self.money)


# 定义一个子类,继承与Father
class Son(Father):
    pass


# 子类创建对象
s = Son()
print(s.money)  # 子类私用继承过来的属性
s.print_info()  # 子类使用继承过来的方法

注意:

  • 子类对象调用方法有一个就近原则
    • 如果本类能找到方法,直接调用本类的方法
    • 如果本类找不到,则调用父类继承过来的方法

2. 分类

2.1 单继承

  • 单继承:子类只继承一个父类
# 定义一个父类, Animal
class Animal(object):
    def eat(self):
        print('吃东西')


# 定义一个子类,只有一个父类
class Dog(Animal):
    pass


# 创建一个子类对象
dog1 = Dog()
dog1.eat()

2.2 多层继承

  • 多层继承:继承关系为多层传递,如生活中的爷爷、父亲、儿子
# 定义一个爷爷类, Animal
class Animal(object):
    def eat(self):
        print('吃东西')


# 定义一个父亲类
class Dog(Animal):
    def drink(self):
        print('喝东西')


# 定义一个儿子类
class SuperDog(Dog):
    pass


# 创建对象
sd = SuperDog()
sd.eat()
sd.drink()

2.3 多继承

1. 简介

1.1 定义
  • 所谓多继承,即子类有多个父类,并且具有它们的特征。
    多继承
1.2 语法格式
class 子类名(父类1, 父类2, ……):
    pass

示例代码:

# 定义2个类,它们没有继承关系,是平级的
class SmallDog(object):
    def eat(self):
        print('吃小东西')


# 再定义一个类
class BigDog(object):
    def drink(self):
        print('大口喝水')


# 定义一个子类,多继承于上面2个父类
class SuperDog(SmallDog, BigDog):
    pass


# 定义子类对象,调用方法
sd = SuperDog()
sd.eat()
sd.drink()

运行结果:

吃小东西
大口喝水

2. 操作

2.1查看类的继承顺序
  • 查看类的继承顺序:类名.__mro__
    示例代码:
# 定义2个类,它们没有继承关系,是平级的
class SmallDog(object):
    def eat(self):
        print('吃小东西')


# 再定义一个类
class BigDog(object):
    def drink(self):
        print('大口喝水')


# 定义一个子类,多继承于上面2个父类
class SuperDog(SmallDog, BigDog):
    pass


# 查看类的继承顺序
print(SuperDog.__mro__)

运行结果:

(<class '__main__.SuperDog'>, <class '__main__.SmallDog'>, <class '__main__.BigDog'>, <class 'object'>)
2.2 调用父类同名方法
1. 默认调用情况
  • 如果继承过来的2个父类的方法同名,默认调用先继承父类的同名方法
# 定义2个类,它们没有继承关系,是平级的
class SmallDog(object):
    def eat(self):
        print('吃小东西')


# 再定义一个类
class BigDog(object):
    def eat(self):
        print('啃大骨头')


# 定义一个子类,多继承于上面2个父类
class SuperDog(SmallDog, BigDog):
    pass


# 定义子类对象,调用方法
sd = SuperDog()
sd.eat()  # 默认先调用先继承的父类,即 SmallDog

运行结果:

吃小东西
2. 子类重写父类同名方法
  • 父类的方法不能满足子类的需要,可以对父类的方法重写,重写父类方法的目的是为了给他扩展功能
  • 在子类中定义了一个和父类同名的方法(参数也一样),即为对父类的方法重写
  • 子类调用同名方法,默认只会调用子类的
    示例代码:
# 定义一个父类, Animal
class Animal(object):
    # 添加一个type属性
    def __init__(self):
        print('Animal类中的__init__')
        self.type = '动物'

    # 设计一个方法,打印属性
    def print_type(self):
        print('Animal类中的print_type = ', self.type)


# 定义一个子类,继承与Animal
class Dog(Animal):
    # __init__和父类的同名,重写父类同名方法
    def __init__(self):
        print('Dog类中的__init__')
        self.type = '可爱的小狗'

    # print_type和父类的同名,重写父类同名方法
    def print_type(self):
        print('Dog类中的print_type = ', self.type)


# 定义一个子类对象
dog1 = Dog()  # 调用子类的__init__
dog1.print_type()  # 调用子类的print_type()

运行结果:

Dog类中的__init__
Dog类中的print_type =  可爱的小狗
3. 子类调用父类同名方法
  • 子类调用父类同名方法:
    • 父类名.同名方法(self, 形参1, ……):调用指定的父类
    • super(类名, self).同名方法(形参1, ……):调用继承顺序中类名的下一个类的同名方法
    • super().同名方法(形参1, ……):调用先继承父类的同名方法(是方法2的简写,比较推荐)
      示例代码:
# 定义2个类,它们没有继承关系,是平级的
class SmallDog(object):
    def eat(self):
        print('吃小东西')


# 再定义一个类
class BigDog(object):
    def eat(self):
        print('啃大骨头')


# 定义一个子类,多继承于上面2个父类
class SuperDog(SmallDog, BigDog):
    def eat(self):
        print('吃蟠桃')
        print('='*20)

        # 子类调用父类同名方法:
        # 1. 父类名.同名方法(self, 形参1, ……)
        SmallDog.eat(self)  # 调用SmallDog的eat()
        print('=' * 20)

        # 2. super(类名, self).同名方法(形参1, ……):调用继承顺序中类名的下一个类的同名方法
        # 继承顺序中,SmallDog的下一个类是BigDog,所以,调用BigDog的eat()
        super(SmallDog, self).eat()
        print('=' * 20)

        # 3. super().同名方法(形参1, ……) :调用先继承父类的同名方法
        super().eat()


# 定义子类对象,调用方法
sd = SuperDog()
sd.eat()

运行结果:

吃蟠桃
====================
吃小东西
====================
啃大骨头
====================
吃小东西

示例代码:

# 定义一个父类, Animal
class Animal(object):
    # 添加一个type属性
    def __init__(self):
        print('Animal类中的__init__')
        self.type = '动物'

    # 设计一个方法,打印属性
    def print_type(self):
        print('Animal类中的print_type = ', self.type)


# 定义一个子类,继承与Animal
class Dog(Animal):
    # __init__和父类的同名,重写父类同名方法
    def __init__(self):
        print('Dog类中的__init__')
        self.type = '可爱的小狗'

    # print_type和父类的同名,重写父类同名方法
    def print_type(self):
        print('Dog类中的print_type = ', self.type)
        print('='*20)

        # 调用父类同名函数
        # 方法1: 父类名.同名方法(self, 形参1, ……)
        Animal.__init__(self)
        Animal.print_type(self)
        print('=' * 20)

        # 方法2:super(子类名, self).同名方法(形参1, ……)
        super(Dog, self).__init__()
        super(Dog, self).print_type()
        print('=' * 20)

        # 方法3:super().同名方法(形参1, ……) # 是 4.2 方法的简写
        # 推荐使用的方法
        super().__init__()
        super().print_type()


# 定义一个子类对象
dog1 = Dog()  # 调用子类的__init__
dog1.print_type()  # 调用子类的print_type()

运行结果:

Dog类中的__init__
Dog类中的print_type =  可爱的小狗
====================
Animal类中的__init__
Animal类中的print_type =  动物
====================
Animal类中的__init__
Animal类中的print_type =  动物
====================
Animal类中的__init__
Animal类中的print_type =  动物

3.私有和继承

3.1 权限

权限有属性权限和方法权限

1. 私有属性

  • 如果在属性名前面加了2个下划线’__’,则表明该属性是私有属性,否则为公有属性
  • 私有属性只能在类的内部访问
"""
私有属性:
    1. __(2个下划线)开头的属性,就是私有属性
    2. 只能在本类的内部访问,在类的外面无法直接访问
"""
class Dog(object):
    # 添加属性
    def __init__(self):
        self.__baby_count = 0   # 私有属性,以__(2个下划线)开头的属性
        self.age = 1    # 公有属性

    def print_info(self):
        print(self.__baby_count)


# 类的外部
# 创建对象
dog1 = Dog()
# print(dog1.__baby_count) # err, 私有属性,在类的外面无法直接访问
print(dog1.age)

dog1.print_info()

2. 私有方法

  • 私有方法和私有属性类似,在方法名前面加了2个下划线’__’,则表明该方法是私有方法
  • 私有方法只能在类内部使用
"""
私有方法:
    1. __(2个下划线)开头的方法,就是私有方法
    2. 只能在本类的内部访问,在类的外面无法直接访问
    3. 在类的内部调用实例方法的语法格式:self.方法名()
"""


class Dog(object):
    def __init__(self):
        self.__baby_count = 0 # 私有属性,以__(2个下划线)开头的属性
        self.age = 1

    def print_info(self):
        print(self.__baby_count)
        self.__leave()

    # 定义一个私有方法
    def __leave(self):
        print('休产假了')


dog1 = Dog()
dog1.print_info()
# AttributeError: 'Dog' object has no attribute '__leave'
# dog1.__leave() # err, 外部不能访问私有方法

3.2 关系

  • 父类中的私有方法、属性不能直接继承使用
  • 可以通过调用继承的父类的共有方法,间接的访问父类的私有方法、属性
# 定义一个父类, Animal
class Animal(object):
    # 添加一个type属性
    def __init__(self):
        self.__type = '动物'  # 私有

    def __leave(self):  # 私有
        print('休产假3个月')

    # 通过公有方法,间接访问私有元素
    def use_private(self):
        print(self.__type)
        self.__leave()


# 定义一个子类
class Dog(Animal):
    def test(self):
        # print(self.__type) # err,私有不能直接继承使用
        # self.__leave() # err,私有不能直接继承使用
        pass


# 创建子类对象
dog1 = Dog()
dog1.use_private()
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值