python 面向对象之继承

news2024/12/23 3:09:58

在这里插入图片描述

文章目录

  • 前言
  • 继承的概念
  • 单继承
  • 多继承
  • 子类重写父类的同名方法和属性
  • 子类调用父类同名的方法和属性
  • 多层继承
  • 私有权限

前言

前面我们已经学习了 python 面向对象的类和对象,那么今天我将为大家分享面向对象的三大特性之一:继承。

继承具有以下特性:

  1. 代码重用:继承允许我们创建一个新的类,并从一个或多个现有的类中继承属性和方法。这使得我们可以避免重复编写相同的代码,提高代码的重用性。通过继承,我们可以在基类的基础上构建更特定和具体的子类。

  2. 扩展功能:通过继承,我们可以在基类的基础上添加新的属性和方法,以实现对基类功能的扩展。这样,我们可以在不修改基类代码的情况下,通过子类来定制或扩展特定的行为。这种灵活性使得我们能够轻松地适应不断变化的需求。

  3. 组织和抽象概念:通过继承,我们可以组织类之间的关系,并以更抽象的方式来表达概念和逻辑。通过将共同的属性和方法放在基类中,我们可以更清晰地表达类之间的关系和层次结构。这种抽象化的设计能够提高代码的可读性和可维护性。

  4. 实现多态性:继承也为实现多态性(Polymorphism)提供了基础。多态性是面向对象编程中非常重要的概念,它可以让我们使用统一的方式处理不同的对象类型。通过继承,我们可以创建不同的子类,它们共享相同的基类接口,但可能有不同的实现方式。这样,我们可以根据具体的对象类型来调用适当的方法,实现更灵活和可扩展的程序设计。

学习好了继承,可以为后面的抽象和多态打好基础,那么就由我带领大家走进 python 继承的世界吧。🚗🚗🚗

继承的概念

在生活中,继承通常是指子女继承父母的财产。但是在 python 中稍有区别,两个具有一定关系的子类和父类,子类会继承父类的所有除了私有的属性和方法。我们可以访问以及修改继承来的属性和方法。

在 python 中使用 class 子类名(父类名): 来表示继承关系。

class Animal():
    def __init__(self):
        self.info = '动物'

    def func(self):
        print(f'属于{self.info}')

class Cat(Animal):
    pass  # 这里pass是占位符,防止报错

cat = Cat()
cat.func()  # 属于动物

继承可以很大程度的提高代码的复用率,提高代码的简洁性。

在python中,其实每一个类都默认继承一个 object 基类

单继承

一个类可以只继承一个类,这种继承关系叫做单继承。

class Master():
    def __init__(self):
        self.wugong = '太极'

    def func(self):
        print(f'身怀绝技:{self.wugong}')

class Prentice(Master):
    pass

zhangsan = Prentice()
zhangsan.func()  # 身怀绝技:太极

多继承

一个类也可以继承多个父类,这种继承关系叫做多继承。

class Master2():
    def __init__(self):
        self.wugong = '闪电五连鞭'

    def func(self):
        print(f'身怀绝技:{self.wugong}')

class Prentice(Master1,Master2):
    pass

zhangsan = Prentice()
zhangsan.func()

在这里插入图片描述
当我们一个继承多个父类的时候,如果没有特地指明,默认使用第一个继承的父类的属性和方法。

如果我们想要查看该类的继承关系,我们可以使用 __mro__ 来查看继承关系。

print(Prentice.__mro__)

在这里插入图片描述

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

子类继承父类的属性和方法,不可能原封不动的继承,子类也可以具有自己的特性。那么这里就需要用到 重写 的方法了。

class Master1():
    def __init__(self):
        self.wugong = '太极'

    def func(self):
        print(f'身怀绝技:{self.wugong}')

class Master2():
    def __init__(self):
        self.wugong = '闪电五连鞭'

    def func(self):
        print(f'身怀绝技:{self.wugong}')

class Prentice(Master1,Master2):
    def __init__(self):
        self.wugong = '太极+轻功'

    def func(self):
        print(f'身怀绝技:{self.wugong}')

zhangsan = Prentice()
zhangsan.func()  # 身怀绝技:太极+轻功

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

当我们在子类中调用和父类具有相同名字的属性和方法的时候,默认会调用子类具有的属性和方法。

class Master1():
    def __init__(self):
        self.wugong = '太极'

    def func(self):
        print(f'身怀绝技:{self.wugong}')

class Master2():
    def __init__(self):
        self.wugong = '闪电五连鞭'

    def func(self):
        print(f'身怀绝技:{self.wugong}')

class Prentice(Master1,Master2):
    def __init__(self):
        self.wugong = '火星大力拳'

    def func(self):
        print(f'身怀绝技:{self.wugong}')

zhangsan = Prentice()
zhangsan.func()  # 身怀绝技:火星大力拳

那么如果我们要在父类中调用具有同名的父类的属性和方法该怎么做呢?

  • 如果是先调用了父类的属性和方法,父类的属性和方法会覆盖子类的属性和方法,所以如果我们想要使用子类自己的属性和方法,需要调用子类自己的初始化方法。
  • 如果我们想要在子类中调用父类的属性和方法,我们也需要先调用父类的初始化方法。

先调用父类的初始化方法,然后再使用 父类类名.方法(self) 来调用父类的方法。

class Master():
    def __init__(self):
        self.wugong = '太极'

    def func(self):
        print(f'身怀绝技:{self.wugong}')

class Prentice(Master):
    def __init__(self):
        self.wugong = '闪电五连鞭'

    def func(self):
        print(f'身怀绝技:{self.wugong}')

    def func1(self):
        Master.__init__(self)  # 调用父类的初始化方法
        Master.func(self)

    def func2(self):
        self.func()

zhangsan = Prentice()
zhangsan.func1()
zhangsan.func2()

在这里插入图片描述

当我们在子类中调用父类的初始化方法或者方法的时候,函数的参数列表必须加上 self ,否则就会报错。

当我们在子类中先调用父类的属性和方法的时候,再调用同名的子类自己的方法的时候,如果没有先调用子类自己的初始化方法,我们会发现会使用父类的属性和方法。

    def func2(self):
        self.__init__()
        self.func()
        
zhangsan = Prentice()
zhangsan.func1()
zhangsan.func2()

在这里插入图片描述

我们还可以使用 super() 来调用父类的方法和属性。但是这种 super() 只能调用子类的直接父类,不能调用简介的父类,如果想要调用简介父类,需要在直接父类的方法中使用 super()

super(当前类名,self).函数名

当然super里面的参数也可省略。

class Master():
    def __init__(self):
        self.wugong = '太极'

    def func(self):
        print(f'身怀绝技:{self.wugong}')

class Prentice(Master):
    def __init__(self):
        self.wugong = '闪电五连鞭'

    def func(self):
        print(f'身怀绝技:{self.wugong}')

    def func1(self):
        super().__init__()
        super().func()


zhangsan = Prentice()
zhangsan.func1()  # 身怀绝技:太极

使用 super() 后面的函数参数列表不需要条件self

多层继承

多层继承是指一个子类继承自另一个子类,而该子类又继承自另一个父类的情况。通过多层继承,可以在类之间形成层次结构,使得子类可以继承和重用祖先类的属性和方法。

# 定义基类A
class A:
    def method_A(self):
        print("This is method A")

# 定义中间类B,继承自基类A
class B(A):
    def method_B(self):
        print("This is method B")

# 定义子类C,继承自中间类B
class C(B):
    def method_C(self):
        print("This is method C")

在上述代码中,类A是基类,类B继承自基类A,类C继承自中间类B。这样,类C就拥有了自己的方法method_C,以及继承自类B和类A的方法method_B和method_A。

通过多层继承,实例化类C的对象,我们既可以调用method_C方法,也可以调用从类B和类A继承而来的方法:

obj = C()
obj.method_C()  # 调用C类的方法
obj.method_B()  # 调用B类的方法
obj.method_A()  # 调用A类的方法
This is method C
This is method B
This is method A

需要注意的是,在进行多层继承时,我们要谨慎选择继承关系,以避免出现复杂和难以维护的继承链。合理设计继承关系能够提高代码的可读性和可维护性,同时也要注意避免过度依赖继承,以免造成耦合性过高的问题。

私有权限

父类继承给子类,可以选择性的继承,可以选择有的东西不继承,这些不继承的事物可以被设置成私有权限,私有权限只能在当前类中访问和修改,就算是该类的子类也不能使用。

在 python 中,如果我们想设置私有权限,可以使用连个下划线来修饰方法名或者属性
__xx

class Master():
    def __init__(self):
        self.wugong = '太极'
        self.__name = 'lisi'

    def func(self):
        print(f'身怀绝技:{self.wugong}')

class Prentice(Master):
    def __init__(self):
        self.wugong = '闪电五连鞭'

    def func(self):
        print(super().__name)  3 访问父类的私有权限



zhangsan = Prentice()
zhangsan.func()

在这里插入图片描述
我们不能访问和修改父类中的私有权限

但是呢,我们的父类可以提供接口来供子类或者其他类来获取和修改私有权限。

我们通常使用 get_xx 来获取私有权限值,set_xx 来修改私有权限值。

class Master():
    def __init__(self):
        self.wugong = '太极'
        self.__name = 'lisi'

    def func(self):
        print(f'身怀绝技:{self.wugong}')

    def get_name(self):
        return self.__name

    def set_name(self,name):
        self.__name = name

master = Master()
print(master.get_name())
master.set_name('wangwu')
print(master.get_name())

在这里插入图片描述
在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/746130.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

怎么使用文件高速传输,推荐镭速高速文件传输解决方案

​​随着互联网的发展,文件传输越来越频繁,如何实现文件高速传输已经越来越成为企业发展过程中需要解决的问题,在当今的业务中,随着与客户和供应商以及内部系统的所有通信的数据量不断增加,对 高速文件传输解决方案的需…

全网最新项目:会说话的汤姆猫直播搭建教程(附教学流程)

今天为大家分享一个 汤姆猫直播搭建项目 ,这个项目最近可以说在圈内爆火,我相信很多朋友以前应该都玩过,或者说给自己家小孩子玩过。 -------------------------------------------------------------------- 课程获取:www.yn521.cn/160852…

RabbitMQ【笔记整理+代码案例】

1. 消息队列 1.1. MQ 的相关概念 1.1.1. 什么是 MQ MQ(message queue),从字面意思上看,本质是个队列,FIFO 先入先出,只不过队列中存放的内容是message 而已,还是一种跨进程的通信机制,用于上下游传递消息…

Python应用:什么是爬虫?

文章目录 什么是爬虫虫之初,性本善?出行社交电商搜索引擎政府部门总结 面向监狱编程爬虫的君子协议什么是君子协议君子协议是怎么产生的?君子协议是什么内容?如何查看一个网站的robots协议违反君子协议的案例 参考文献 2022年初的…

装饰器模式:灵活扩展功能的设计利器

装饰器模式是一种结构型设计模式,它允许我们在不改变现有对象结构的情况下,动态地将新功能附加到对象上。本文将深入探讨装饰器模式的原理、结构和使用方法,并通过详细的 Java 示例代码来说明。 1. 装饰器模式的定义 装饰器模式是一种允许我…

Python: 如何批量预处理FY4A L1 DISK和REGC产品?(辐射定标/裁剪/GLT校正/HDF5转TIFF文件等)

目录 01 前言 1.1 想要说 1.2 Requirements 1.3 程序适用数据集 02 函数说明 2.1 读取HDF5文件某一数据集 2.2 读取HDF5文件数据集属性 2.3 对FY4A数据集进行辐射定标 2.4 基于官方地理对照表获取经纬度数据(仅适用DISK) 2.5 依据行列号计算经纬度数据(仅适用DISK) …

C++primer(第五版)第十八章(用于大型程序的工具)

不做大项目的话估计下面的都暂时用不到,包括下一章 大规模应用程序要求:能使用各种库进行协调开发(多人多文件编程);能在独立开发的子系统之间协同处理错误(说人话就是我用了你写的库结果报错了,我们得协调处理好出错的地方);能对比较复杂的应用概念进行建模(定义合理的类,函数…

(工具记录)Log4j2_RCE

0x00 简介 ApacheLog4j2是一个开源的Java日志框架,被广泛地应用在中间件、开发框架与Web应用中。 0x01 漏洞概述 该漏洞是由于Apache Log4j2某些功能存在递归解析功能,未经身份验证的攻击者通过发送特定恶意数据包,可在目标服务器上执行任意…

获取DNF人物坐标值

众所周知DNF是一个没有坐标值显示的游戏。 那么如何才能不碰内存和封包的情况下,获取DNF游戏中人物在当前房间的坐标值呢? 有兴趣的找我交流吧。

Go语言IO模式

Go语言IO模式 IO 操作是我们在编程中不可避免会遇到的,Go语言的 io 包中提供了相关的接口,定义了相应的规范,不同的数 据类型可以根据规范去实现相应的方法,提供更加丰富的功能。 本文主要介绍常见的 IO (输入和输出)模式&…

《MySQL》复合查询和连接

文章目录 查询单行子查询多行子查询合并查询 连接内连接外连接 点睛之笔:无论是多表还是单表,我们都可以认为只有一张表。 只要是表,就可以查询和连接成新表,所以select出来的结果都可以认为成一张表,既然是一张表&…

Python多线程使用详解

概要 多线程是一种并发编程的技术,通过同时执行多个线程来提高程序的性能和效率。在Python中,我们可以使用内置的threading模块来实现多线程编程。 一、创建线程 在使用多线程之前,我们首先需要了解如何创建线程。Python提供了threading模块…

你信不信,只要学几天javascript就可以使用纯原生实现五星评分效果 【附完整代码】

🚀 个人主页 极客小俊 ✍🏻 作者简介:web开发者、设计师、技术分享博主 🐋 希望大家多多支持一下, 我们一起进步!😄 🏅 如果文章对你有帮助的话,欢迎评论 💬点赞&#x1…

动态规划DP(七) 股票交易

1.股票交易 在股票买卖的最佳时机问题中,给定一个数组,数组中的每个元素代表某一天的股票价格。你可以进行多次买入和卖出,但是必须在再次购买前卖出之前的股票。目标是找到最大的利润。 动态规划可以用于解决股票交易类的问题,…

ssl证书和域名过期提醒平台

由于经常忘记了证书是否要过期,导致过期了出现一些访问上的问题 docker安装部署 当然可以接入mysql,默认使用的sqlite version: "3" services:domain-admin:image: mouday/domain-admin:latestcontainer_name: domain-adminvolumes:- ./data:/…

菜鸡shader:L8 UV扰动动画——火焰和简单水面

文章目录 卡通火焰代码最后效果 水面代码最后效果 这此做笔记的两个shader其实是课程的作业,课程主要也是讲UV扰动的概念,因为课程的shader在另一台电脑上,做笔记就暂时不带他们了,简单做下火焰和水面的shader。 卡通火焰 火焰这…

FreeRTOS(队列)

队列 什么是队列? 队列又称消息队列,是一种常用于任务间通信的数据结构,队列可以在任务与任务间、中断和任 务间传递信息。 为什么不使用全局变量? 如果使用全局变量,兔子(任务1)修改了变量 a …

新版studio没法筛选Log

目录 方式一 简单粗暴,针对怀旧者,可切回原版log视图 方式二 学习新的log过滤方法 升级新版本AndroidStudio后,log日志变成以下样子,发现之前过滤error,infor的tab都不见了,瞬间不淡定了,查阅资料才发现…

DAY45:动态规划(五)背包问题:01背包理论基础+二维DP解决01背包问题

文章目录 背包问题大纲01背包01背包暴力解法01背包二维DP解法二维DP数组的解法DP数组含义递推公式初始化二维DP数组(比较重要)遍历顺序(比较重要) 二维DP数组完整版思路总结返回值为什么是二维数组最后一个元素DP推导过程与数组含…

selenium 根据期刊信息获取知网文献信息 pt.1

哈喽大家好,我是咸鱼 之前写过一篇获取知网文献信息的文章,看了下后台数据还挺不错 所以咸鱼决定再写一篇知网文献信息爬取的文章 需要注意的是文章只是针对某一特定期刊的爬取,希望小伙伴们把关注点放在如何分析网页以及如何定位元素上面…