17_python基础—面向对象-继承

一、继承的概念

  • 拓展1:经典类或旧式类

不由任意内置类型派生出的类,称之为经典类。

class 类名:
    代码
    ......
  • 拓展2:新式类
class 类名(object):
    代码

Python面向对象的继承指的是多个类之间的所属关系,即子类默认继承父类的所有属性和方法,具体如下:

# 父类A
class A(object):
    def __init__(self):
        self.num = 1

    def info_print(self):
        print(self.num)

# 子类B
class B(A):
    pass

# 创建对象
result = B()
result.info_print()  # 1

在Python中,所有类默认继承object类,object类是顶级类或基类;其他子类叫做派生类。

二、单继承

2.1 概念和语法

1)概念

继承的概念子类 拥有 父类 的所有 方法属性

在这里插入图片描述

2)语法

class 类名(父类名):

    pass
  • 子类 继承自 父类,可以直接 享受 父类中已经封装好的方法,不需要再次开发
  • 子类 中应该根据 职责,封装 子类特有的 属性和方法

2.2 专业术语

  • Dog 类是 Animal 类的子类Animal 类是 Dog 类的父类Dog 类从 Animal继承
  • Dog 类是 Animal 类的派生类Animal 类是 Dog 类的基类Dog 类从 Animal派生

2.3 继承的传递性

  • C 类从 B 类继承,B 类又从 A 类继承
  • 那么 C 类就具有 B 类和 A 类的所有属性和方法

子类 拥有 父类 以及 父类的父类 中封装的所有 属性方法

2.4 案例

故事主线:一个煎饼果子老师傅,在煎饼果子界摸爬滚打多年,研发了一套精湛的摊煎饼果子的技术。师父要把这套技术传授给他的唯一的最得意的徒弟。

分析:徒弟是不是要继承师父的所有技术?

# 1. 师父类
class Master(object):
    def __init__(self):
        self.kongfu = '[古法煎饼果子配方]'

    def make_cake(self):
        print(f'运用{self.kongfu}制作煎饼果子')

        
# 2. 徒弟类
class Prentice(Master):
    pass


# 3. 创建对象daqiu
daqiu = Prentice()
# 4. 对象访问实例属性
print(daqiu.kongfu)
# 5. 对象调用实例方法
daqiu.make_cake()

三、多继承

3.1 概念和语法

1)概念

  • 子类 可以拥有 多个父类,并且具有 所有父类属性方法
  • 例如:孩子 会继承自己 父亲母亲特性

在这里插入图片描述

2)语法

class 子类名(父类名1, 父类名2...)
    pass

3.2 多继承的使用注意事项

1)问题的提出

  • 如果 不同的父类 中存在 同名的方法子类对象 在调用方法时,会调用 哪一个父类中的方法呢?

提示:开发时,应该尽量避免这种容易产生混淆的情况! —— 如果 父类之间 存在 同名的属性或者方法,应该 尽量避免 使用多继承

在这里插入图片描述

2)Python 中的 MRO —— 方法搜索顺序(知道)

  • Python 中针对 提供了一个 内置属性 __mro__ 可以查看 方法 搜索顺序
  • MRO 是 method resolution order,主要用于 在多继承时判断 方法、属性 的调用 路径
print(C.__mro__)

输出结果

(<class '__main__.C'>, <class '__main__.A'>, <class '__main__.B'>, <class 'object'>)
  • 在搜索方法时,是按照 __mro__ 的输出结果 从左至右 的顺序查找的
  • 如果在当前类中 找到方法,就直接执行,不再搜索
  • 如果 没有找到,就查找下一个类 中是否有对应的方法,如果找到,就直接执行,不再搜索
  • 如果找到最后一个类,还没有找到方法,程序报错

3.3 案例

故事推进:daqiu是个爱学习的好孩子,想学习更多的煎饼果子技术,于是,搜索报班学习煎饼果子技术。

所谓多继承意思就是一个类同时继承了多个父类。

class Master(object):
    def __init__(self):
        self.kongfu = '[古法煎饼果子配方]'

    def make_cake(self):
        print(f'运用{self.kongfu}制作煎饼果子')


# 创建学校类
class School(object):
    def __init__(self):
        self.kongfu = '[学校煎饼果子配方]'

    def make_cake(self):
        print(f'运用{self.kongfu}制作煎饼果子')


class Prentice(School, Master):
    pass

# 3. 用徒弟类创建对象,调用实例属性和方法
daqiu = Prentice()
print(daqiu.kongfu)
daqiu.make_cake()

注意:当一个类有多个父类的时候,默认使用第一个父类的同名属性和方法。

四、子类重写父类同名方法和属性

如果子类和父类拥有同名方法和属性,用子类创建对象,这个对象调用同名方法和属性,调用的是子类封装好的方法和属性,而不再是父类里面的。

故事:daqiu掌握了师父和培训的技术后,自己潜心钻研出自己的独门配方的一套全新的煎饼果子技术。

class Master(object):
    def __init__(self):
        self.kongfu = '[古法煎饼果子配方]'

    def make_cake(self):
        print(f'运用{self.kongfu}制作煎饼果子')


class School(object):
    def __init__(self):
        self.kongfu = '[学校煎饼果子配方]'

    def make_cake(self):
        print(f'运用{self.kongfu}制作煎饼果子')


# 独创配方
class Prentice(School, Master):
    def __init__(self):
        self.kongfu = '[独创煎饼果子配方]'

    def make_cake(self):
        print(f'运用{self.kongfu}制作煎饼果子')


daqiu = Prentice()
print(daqiu.kongfu)
daqiu.make_cake()


# 一个类继承的父类和这些父类的层级关系
print(Prentice.__mro__)

子类和父类具有同名属性和方法,默认使用子类的同名属性和方法。

五、调用父类方法(两种方式)

  • 方法一:
父类名.方法(self)
  • 方法二:
super().父类方法

5.1 子类调用父类的同名方法和属性

故事:很多顾客都希望也能吃到古法和学校的技术的煎饼果子。

class Master(object):
    def __init__(self):
        self.kongfu = '[古法煎饼果子配方]'

    def make_cake(self):
        print(f'运用{self.kongfu}制作煎饼果子')


class School(object):
    def __init__(self):
        self.kongfu = '[学校煎饼果子配方]'

    def make_cake(self):
        print(f'运用{self.kongfu}制作煎饼果子')


class Prentice(School, Master):
    def __init__(self):
        self.kongfu = '[独创煎饼果子配方]'

    def make_cake(self):
        # 如果是先调用了父类的属性和方法,父类属性会覆盖子类属性,故在调用属性前,先调用自己子类的初始化
        self.__init__()
        print(f'运用{self.kongfu}制作煎饼果子')

    # 调用父类方法,但是为保证调用到的也是父类的属性,必须在调用方法前调用父类的初始化
    def make_master_cake(self):
        Master.__init__(self)
        Master.make_cake(self)

    def make_school_cake(self):
        School.__init__(self)
        School.make_cake(self)


daqiu = Prentice()

daqiu.make_cake()

daqiu.make_master_cake()

daqiu.make_school_cake()

daqiu.make_cake()

5.2 super()调用父类方法

1)用法

  • 在子类中 重写 父类的方法
  • 在需要的位置使用 super().父类方法 来调用父类方法的执行
super().父类方法
  • 代码其他的位置针对子类的需求,编写 子类特有的代码实现

2)super

  • Pythonsuper 是一个 特殊的类
  • super() 就是使用 super 类创建出来的对象
  • 最常 使用的场景就是在 重写父类方法时,调用 在父类中封装的方法实现

3)案例

class Master(object):
    def __init__(self):
        self.kongfu = '[古法煎饼果子配方]'

    def make_cake(self):
        print(f'运用{self.kongfu}制作煎饼果子')


class School(Master):
    def __init__(self):
        self.kongfu = '[学校煎饼果子配方]'

    def make_cake(self):
        print(f'运用{self.kongfu}制作煎饼果子')

        # 方法2.1 带参数
        # super(School, self).__init__()
        # super(School, self).make_cake()

        # 方法2.2 无参数
        super().__init__()
        super().make_cake()


class Prentice(School):
    def __init__(self):
        self.kongfu = '[独创煎饼果子技术]'

    def make_cake(self):
        self.__init__()
        print(f'运用{self.kongfu}制作煎饼果子')

    # 子类调用父类的同名方法和属性:把父类的同名属性和方法再次封装
    def make_master_cake(self):
        Master.__init__(self)
        Master.make_cake(self)

    def make_school_cake(self):
        School.__init__(self)
        School.make_cake(self)

    # 一次性调用父类的同名属性和方法
    def make_old_cake(self):
        # 方法一:代码冗余;父类类名如果变化,这里代码需要频繁修改
        # Master.__init__(self)
        # Master.make_cake(self)
        # School.__init__(self)
        # School.make_cake(self)

        # 方法二: super()
        # 方法2.1 super(当前类名, self).函数()
        # super(Prentice, self).__init__()
        # super(Prentice, self).make_cake()

        # 方法2.2 super().函数()
        super().__init__()
        super().make_cake()


daqiu = Prentice()

daqiu.make_old_cake()

注意:使用super() 可以自动查找父类。调用顺序遵循 __mro__ 类属性的顺序。比较适合单继承使用。

六、多层继承

故事:N年后,daqiu老了,想要把所有技术传承给自己的徒弟。

class Master(object):
    def __init__(self):
        self.kongfu = '[古法煎饼果子配方]'

    def make_cake(self):
        print(f'运用{self.kongfu}制作煎饼果子')


class School(object):
    def __init__(self):
        self.kongfu = '[学校煎饼果子配方]'

    def make_cake(self):
        print(f'运用{self.kongfu}制作煎饼果子')


class Prentice(School, Master):
    def __init__(self):
        self.kongfu = '[独创煎饼果子配方]'

    def make_cake(self):
        self.__init__()
        print(f'运用{self.kongfu}制作煎饼果子')

    def make_master_cake(self):
        Master.__init__(self)
        Master.make_cake(self)

    def make_school_cake(self):
        School.__init__(self)
        School.make_cake(self)

# 步骤:1. 创建类Tusun, 用这个类创建对象;2. 用这个对象调用父类的属性或方法看能否成功
# 徒孙类
class Tusun(Prentice):
    pass


xiaoqiu = Tusun()

xiaoqiu.make_cake()

xiaoqiu.make_school_cake()

xiaoqiu.make_master_cake()

运用[独创煎饼果子配方]制作煎饼果子
运用[学校煎饼果子配方]制作煎饼果子
运用[古法煎饼果子配方]制作煎饼果子

七、父类 私有属性 和 私有方法

7.1 定义私有属性和方法

  1. 子类对象 不能 在自己的方法内部,直接 访问 父类的 私有属性私有方法
  2. 子类对象 可以通过 父类公有方法 间接 访问到 私有属性私有方法

在Python中,可以为实例属性和方法设置私有权限,即设置某个实例属性或实例方法不继承给子类。

故事:daqiu把技术传承给徒弟的同时,不想把自己的钱(2000000个亿)继承给徒弟,这个时候就要为这个实例属性设置私有权限。

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

class Master(object):
    def __init__(self):
        self.kongfu = '[古法煎饼果子配方]'

    def make_cake(self):
        print(f'运用{self.kongfu}制作煎饼果子')


class School(object):
    def __init__(self):
        self.kongfu = '[学校煎饼果子配方]'

    def make_cake(self):
        print(f'运用{self.kongfu}制作煎饼果子')


class Prentice(School, Master):
    def __init__(self):
        self.kongfu = '[独创煎饼果子配方]'
        # 定义私有属性
        self.__money = 2000000

    # 定义私有方法
    def __info_print(self):
        print(self.kongfu)
        print(self.__money)

    def make_cake(self):
        self.__init__()
        print(f'运用{self.kongfu}制作煎饼果子')

    def make_master_cake(self):
        Master.__init__(self)
        Master.make_cake(self)

    def make_school_cake(self):
        School.__init__(self)
        School.make_cake(self)


# 徒孙类
class Tusun(Prentice):
    pass


daqiu = Prentice()
# 对象不能访问私有属性和私有方法
# print(daqiu.__money)
# daqiu.__info_print()

xiaoqiu = Tusun()
# 子类无法继承父类的私有属性和私有方法
# print(xiaoqiu.__money)  # 无法访问实例属性__money
# xiaoqiu.__info_print()

注意:私有属性和私有方法只能在类里面访问和修改。

7.2 获取和修改私有属性值

在Python中,一般定义函数名get_xx用来获取私有属性,定义set_xx用来修改私有属性值。

class Master(object):
    def __init__(self):
        self.kongfu = '[古法煎饼果子配方]'

    def make_cake(self):
        print(f'运用{self.kongfu}制作煎饼果子')


class School(object):
    def __init__(self):
        self.kongfu = '[黑马煎饼果子配方]'

    def make_cake(self):
        print(f'运用{self.kongfu}制作煎饼果子')


class Prentice(School, Master):
    def __init__(self):
        self.kongfu = '[独创煎饼果子配方]'
        self.__money = 2000000

    # 获取私有属性
    def get_money(self):
        return self.__money

    # 修改私有属性
    def set_money(self):
        self.__money = 500

    def __info_print(self):
        print(self.kongfu)
        print(self.__money)

    def make_cake(self):
        self.__init__()
        print(f'运用{self.kongfu}制作煎饼果子')

    def make_master_cake(self):
        Master.__init__(self)
        Master.make_cake(self)

    def make_school_cake(self):
        School.__init__(self)
        School.make_cake(self)


# 徒孙类
class Tusun(Prentice):
    pass


daqiu = Prentice()

xiaoqiu = Tusun()
# 调用get_money函数获取私有属性money的值
print(xiaoqiu.get_money())
# 调用set_money函数修改私有属性money的值
xiaoqiu.set_money()
print(xiaoqiu.get_money())

八、新式类与旧式(经典)类

objectPython 为所有对象提供的 基类,提供有一些内置的属性和方法,可以使用 dir 函数查看

  • 新式类:以 object 为基类的类,推荐使用
  • 经典类:不以 object 为基类的类,不推荐使用
  • Python 3.x 中定义类时,如果没有指定父类,会 默认使用 object 作为该类的 基类 —— Python 3.x 中定义的类都是 新式类
  • Python 2.x 中定义类时,如果没有指定父类,则不会以 object 作为 基类

新式类经典类 在多继承时 —— 会影响到方法的搜索顺序

为了保证编写的代码能够同时在 Python 2.xPython 3.x 运行!
今后在定义类时,如果没有父类,建议统一继承自 object

class 类名(object):    
	pass

九、总结

  • 继承的特点

    • 子类默认拥有父类的所有属性和方法
    • 子类重写父类同名方法和属性
    • 子类调用父类同名方法和属性
  • super()方法快速调用父类方法

  • 私有权限

    • 不能继承给子类的属性和方法需要添加私有权限
    • 语法
class 类名():
  # 私有属性
  __属性名 =# 私有方法
  def __函数名(self):
    代码
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

少云清

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值