day30

今日内容概要

  • 继承(面向对象中得核心)

    • 单继承 多继承

  • 单继承下的属性查找

  • 多继承下的属性查找

  • super和mro的使用

  • 多态和鸭子类型

继承(核心)

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

1.什么是继承

继承就是一种新建类的方式,新建出来的类我们称为‘子类或者叫派生类’,被继承的类我们称之为是‘父类或者基类’

   当然出来的类子类可以遗传父类的所有属性

2.为什么要用继承

类解决了什么问题:对象与对象之间的代码冗余问题

继承解决了什么问题:类与类之间的代码冗余问题

3.怎么使用继承

经典类:没有继承object类的子子孙孙类都是经典类

新式类:继承了object类的子子孙孙类都是新式类

只有在python2中才区分经典类和新式类,如果是python3的版本,所有类都是新式类,也就是说在python3中默认的类都是继承了object类,在python3中没有了经典类和新式类的说法了

 class Parent1:passclass Parent2(object):pass

”Sub1继承了Parent1的类,Sub1就称为是子类,Parent1类就称为是父类或者叫基类“

单继承:一个类只继承了一个类,一个类继承了两个或者两个以上的类就是多继承了

class Sub1(Parent1):pass

多继承的类:Sub2就是子类,Parent1和Parent2都是父类

class Sub2(Parent1, Parent2):passprint(Sub1.__bases__) # (<class '__main__.Parent1'>,)
print(Sub2.__bases__) # (<class '__main__.Parent1'>, <class '__main__.Parent2'>)

继承的实际案例

class People():school = 'SH'def __init__(self, name, age, gender):self.name = nameself.age = ageself.gender = genderclass Student(People):def __init__(self, name, age, gender, course=None):if course is None:course = []"""子类里面一定再次调用父类的__init__方法"""People.__init__(self, name, age, gender) # 指名道姓的调用方法self.course = coursedef choose_course(self):print('%s 选课成功, %s' % (self.name, self.course))stu = Student('ly', 20, 'male')
print(stu.school)  # SH 属性的查找
print(stu.name)
print(stu.age)
print(stu.gender)class Teacher(People):def __init__(self, name, age, gender, level):People.__init__(self, name, age, gender)self.level = leveldef score(self, stu_name):print('%s 得了%s分' % (stu_name, 10))tea = Teacher('kevin', 19, 'female')
print(tea.name)
print(tea.age)
print(tea.gender)

属性查找

有了继承关系,对象在查找属性时,先从对象自己的__dict__中找,如果没有则去子类中找,然后再去父类中找.......

>>> class Foo:
...     def f1(self):
...         print('Foo.f1')
...     def f2(self):
...         print('Foo.f2')
...         self.f1()
... 
>>> class Bar(Foo):
...     def f1(self):
...         print('Foo.f1')
... 
>>> b=Bar()
>>> b.f2()
Foo.f2
Foo.f1

b.f2()会在父类Foo中找到f2,先打印Foo.f2,然后执行到self.f1(),即b.f1(),仍会按照:对象->类Bar->父类Foo的顺序依次找下去,在类Bar中找到f1,因而打印结果为Foo.f1

父类如果不想让子类覆盖自己的方法,可以采用双下划线开头的方式将方法设置为私有的

>>> class Foo:
...     def __f1(self): # 变形为_Foo__fa
...         print('Foo.f1') 
...     def f2(self):
...         print('Foo.f2')
...         self.__f1() # 变形为self._Foo__fa,因而只会调用自己所在的类中的方法
... 
>>> class Bar(Foo):
...     def __f1(self): # 变形为_Bar__f1
...         print('Foo.f1')
... 
>>> 
>>> b=Bar()
>>> b.f2() #在父类中找到f2方法,进而调用b._Foo__f1()方法,同样是在父类中找到该方法
Foo.f2
Foo.f1

继承的实现原理

菱形问题

大多数面向对象语言都不支持多继承,而在python中,一个子类是可以同时继承多个父类的,这固然可以带来一个子类可以对多个不同父类加以重用的好处,但也有可能引发著名的Diamond problem菱形问题(或称钻石问题,有时候也被称为“死亡钻石”),菱形其实就是对下面这种继承结构的形象比喻

 A类在顶部,B类和C类分别位于其下方,D类在底部将两者连接在一起形成菱形。

这种继承结构下导致的问题称之为菱形问题:如果A中有一个方法,B和/或C都重写了该方法,而D没有重写它,那么D继承的是哪个版本的方法:B的还是C的?如下所示

class A(object):def test(self):print('from A')class B(A):def test(self):print('from B')class C(A):def test(self):print('from C')class D(B,C):passobj = D()
obj.test() # 结果为:from B

要想搞明白obj.test()是如何找到方法test的,需要了解python的继承实现原理

继承原理

python到底是如何实现继承的呢?对于你定义的每一个类,Python都会计算出一个方法解析顺序(MRO)列表,该MRO列表就是一个简单的所有的基类的线性顺序列表如下

>>> D.mro() # 新式类内置了mro方法可以查看线性列表的内容,经典类没有该内置该方法
[<class '__main__.D'>, <class '__main__.B'>, <class '__main__.C'>, <class '__main__.A'>, <class 'object'>]

python会在MRO列表上从左到右开始查找基类,直到找到第一个匹配这个属性的类为止。而这个MRO列表的构造是通过一个C3线性化算法来实现的。我们不去深究这个算法的数学原理,它实际上就是合并所有父类的MRO列表并遵循如下三条准则:

1.子类会先于父类被检查
2.多个父类会根据它们在列表中的顺序被检查
3.如果对下一个类存在两个合法的选择,选择第一个父类

所以obj.test()的查找顺序是,先从对象obj本身的属性里找到方法test,没有找到,则参照属性查找的发起者(即obj)所处类D的MRO列表来依次检索,首先在类D中未找到,然后再B中找到方法test

1.由对象发起的属性查找,会从对象自身的属性里检索,没有则会按照对象的类.mro()规定的顺序依次找下去,
2.由类发起的属性查找,会按照当前类.mro()规定的顺序依次找下去,

深度优先和广度优先

参照下述代码,多继承结构为非菱形结构,此时,会按照先找B这一条分支,然后再找C这一条分支,最后找D这一条分支的顺序直到找到我们想要的属性

class E:def test(self):print('from E')class F:def test(self):print('from F')class B(E):def test(self):print('from B')class C(F):def test(self):print('from C')class D:def test(self):print('from D')class A(B, C, D):# def test(self):#     print('from A')passprint(A.mro())
'''
[<class '__main__.A'>, <class '__main__.B'>, <class '__main__.E'>, <class '__main__.C'>, <class '__main__.F'>, <class '__main__.D'>, <class 'object'>]
'''obj = A()
obj.test() # 结果为:from B
# 可依次注释上述类中的方法test来进行验证

 如果继承关系为菱形结构,那么经典类与新式类会有不同MRO,分别对应属性的两种查找方式:深度优先和广度优先

class G: # 在python2中,未继承object的类及其子类,都是经典类def test(self):print('from G')class E(G):def test(self):print('from E')class F(G):def test(self):print('from F')class B(E):def test(self):print('from B')class C(F):def test(self):print('from C')class D(G):def test(self):print('from D')class A(B,C,D):# def test(self):#     print('from A')passobj = A()
obj.test() # 如上图,查找顺序为:obj->A->B->E->G->C->F->D->object
# 可依次注释上述类中的方法test来进行验证,注意请在python2.x中进行测试

 

 

class G(object):def test(self):print('from G')class E(G):def test(self):print('from E')class F(G):def test(self):print('from F')class B(E):def test(self):print('from B')class C(F):def test(self):print('from C')class D(G):def test(self):print('from D')class A(B,C,D):# def test(self):#     print('from A')passobj = A()
obj.test() # 如上图,查找顺序为:obj->A->B->E->C->F->D->G->object
# 可依次注释上述类中的方法test来进行验证

super的使用

#A没有继承B,但是A内super会基于C.mro()继续往后找
class A:def test(self):super().test()
class B:def test(self):print('from B')
class C(A,B):passc=C()
c.test() #打印结果:from B

多态和鸭子类型

多态它是面向对象的三大特征之一

什么是多态?  同一种事物的多种形态

举例:

    水:气态水、液态水、固态水                                                                                                             动物:人 鸡 狗 猪等都是动物的一种形态

之所以说人、鸡、狗、猪是动物,是因为他们具备动物的特征,speak功能

import abc # abstract class 抽象类   具体的Specificclass Animal(metaclass=abc.ABCMeta): # 把animal类变成了抽象类"""父类中得方法不是为了实现逻辑的,实现功能的,而是单纯的为了限制子类的行为"""@abc.abstractmethod # 把抽象类中得方法变成抽象方法, 它不实现具体的功能,就是单纯的为了限制子类中的方法def speak(self):pass@abc.abstractmethoddef jiao(self):pass"""抽象类和普通类有什么区别? 抽象类只能够被继承、不能够被实例化"""# Animal() # Can't instantiate abstract class Animal with abstract methods speak"""怎么限制子类People类必须有speak功能? 我们可以在父类中来限制子类的行为,其实就是限制子类中必须有某些方法""""""Python崇尚的是鸭子类型""""""鸭子类型就是更多的关注的是对象的行为,而不是对象的类型"""class People(Animal):def speak(self):pass# print('from People.speak')def jiao(self):passclass Dog(Animal):def speak(self):passclass Pig(Animal):def speak(self):pass"""多态带来的特性:在不考虑对象类型的情况下,直接调用对象的方法或者属性"""
def animal(obj):return obj.speak()animal(obj)
animal(obj1)
animal(obj2)"""面试题:请举出Python中使用多态的例子:len"""len('hello')
len([1,2,3,4])
len((1,2,3,4))def len(obj):return obj.__len__
len('helloworld')
len([1,2,3,4])
len((1,2,3,4))

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

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

仅个人记录:复现dotspatialdemo、打包、

复现dotspatialdemo 原始文件 一、新建项目、工具箱设置&#xff0c;项目引用等看上一篇 二、根据Form1.Designer.cs设计界面Form1.cs[设计] SplitContainer控件&#xff1a;将容器的显示区域分成两个大小可调的、可以向其中添加控件的面板。 legend控件&#xff1a;图例 map控…

System Generator初体验FIR滤波器

文章目录 前言一、介绍1、目标2、过程 二、步骤 1&#xff1a;在 FPGA 中创建设计1、打开 Lab1_1.slx 文件2、运行仿真3、使用 System Generator 创建 FIR 滤波器<1>、从库浏览器寻找需要的模块<2>、配置系统生成器块<3>、在 FPGA 上实现设计 三、步骤 2&…

[React] react-redux基本使用

文章目录 1.redux2.安装redux3.操作redux3.1 创建最为核心的store3.2 创建为store工作的reducer3.3 redux的响应式处理 4.完整版redux4.1 完善actionCreators4.2 thunk中间件 5.react-redux5.1 Count容器组件5.2 connect函数5.3 Provider 1.redux redux原理图 actionCreators:…

一文熟练使用python修改Excel中的数据

使用python修改Excel中的内容 1.初级修改 1.1 openpyxl库的功能&#xff1a; openpyxl模块是一个读写Excel 2010文档的Python库&#xff0c;如果要处理更早格式的Excel文档&#xff0c;需要用到额外的库&#xff0c;例如Xlwings。openpyxl是一个比较综合的工具&#xff0c;能…

MOM与MES管理系统有哪些本质上的区别

随着企业业务的不断发展&#xff0c;许多制造企业开始面临车间管理失控、生产不透明等问题。这时候&#xff0c;很多企业选择上线MES生产管理系统来提高生产管理水平。然而&#xff0c;随着企业业务的不断拓展&#xff0c;MES系统也逐渐暴露出其局限性。于是&#xff0c;MOM平台…

LeetCode 143.重排链表

题目链接 力扣&#xff08;LeetCode&#xff09;官网 - 全球极客挚爱的技术成长平台 题目解析 分析题目后我们可以直接进行模拟实现。 具体用到的就是我们之前的知识的结合&#xff0c;首先使用快慢指针找到链表的中间结点。然后将后半段链表给翻转一下&#xff0c;然后再让这…

Uniapp 新手专用 抖音登录 获取用户头像、名称、openid、unionid、anonymous_openid、session_key

TC-dylogin 一定请选择 源码授权版 教程 第一步 将代码拷贝至您所需要的页面 该代码位置&#xff1a;pages/index.vue 第二步 修改appid和secret 第三步 获取appid和secret 获取appid和secret链接 注意事项 为了安全&#xff0c;我将默认的自己的appid和secret在云函数中删…

化妆品用乙基己基甘油全球市场总体规模2023-2029

乙基己基甘油又名辛氧基甘油&#xff0c;分子式 C11H24O3&#xff0c;分子量 204.306&#xff0c;沸点 325℃&#xff0c;密度 0.962&#xff0c;无色液体&#xff0c;涂抹性能适中的润肤剂、保湿剂及润湿剂。它能够在提高配方滋润效果的同时又具有柔滑的肤感。加入在某些膏霜体…

使用python利用merge+sort函数对excel进行连接并排序

好久没更新了&#xff0c;天天玩短视频了。现在发现找点学习资料真的好难。 10.1期间偶然拿到一本书 本书是2022年出版的&#xff0c;看了一下不错&#xff0c;根据上面的案例结合&#xff0c;公司经营整合案例&#xff0c;分享一下。 数据内容来源于书中内容&#xff0c;仅供…

【网络安全 --- kali2022安装】kali2022 超详细的安装教程(提供镜像)

如果你还没有安装vmware 虚拟机&#xff0c;请参考下面博客安装 【网络安全 --- 工具安装】VMware 16.0 详细安装过程&#xff08;提供资源&#xff09;-CSDN博客【网络安全 --- 工具安装】VMware 16.0 详细安装过程&#xff08;提供资源&#xff09;https://blog.csdn.net/m0…

在Linux中通过docker安装appnode面板

先在Linux中安装docker&#xff0c;然后在docker中安装appnode面板&#xff0c;并进行docker网络端口映射。 安装docker 第一步&#xff0c;卸载旧版本docker。 若系统中已安装旧版本docker&#xff0c;则需要卸载旧版本docker以及与旧版本docker相关的依赖项。 命令&#…

力扣(LeetCode)2034. 股票价格波动(C++)

哈希表有序集合 请看本题解的分析&#xff1a; 题目的关键是四大操作&#xff0c;其中 current/maximum/minimum 明示我们&#xff0c;数据流应有快速找到一些数据的能力&#xff1a; 时间戳最大的股票所对应的价格&#xff0c;即题目所定义的最新股票价格在当前数据流节点&a…

微服务技术栈-Nacos配置管理和Feign远程调用

文章目录 前言一、统一配置管理1.添加配置文件2.微服务拉取配置3.配置共享 三、Feign远程调用总结 前言 在上篇文章中介绍了微服务技术栈中Nacos这个组件的概念&#xff0c;Nacos除了可以做注册中心&#xff0c;同样可以做配置管理来使用。同时我们将学习一种新的远程调用方式…

Ant Design of React组件引用及路由跳转

Ant Design of React 学习笔记&#xff08;2&#xff09; Ant Design of React组件引用及路由跳转&#xff0c;接着笔记(1)继续 这里我们主要3点&#xff1a;1.使用Ant的组件&#xff1b;2&#xff0c;如何引用页面组件&#xff1b;3&#xff0c;路由导航跳转 这是我的目录结…

一文读懂Base64

这几天在和第三方交互的时候&#xff0c;对方返回的数据是base64格式的数据&#xff0c;所以这两天又彻底捋了下Base64的来龙去脉。之前看过一篇文章说的非常好&#xff08;再找到给加上链接&#xff09;&#xff0c;我在这不详细说明了&#xff0c;只说转换过程。 还是使用中…

【算法刷题】【链表】链表内指定区间反转:将一个节点数为 size 链表 m 位置到 n 位置之间的区间反转,要求时间复杂度 O(n),空间复杂度)O(1)。

题目 解题 import java.util.*;/** public class ListNode {* int val;* ListNode next null;* public ListNode(int val) {* this.val val;* }* }*/public class Solution {/*** 代码中的类名、方法名、参数名已经指定&#xff0c;请勿修改&#xff0c;直接返回…

uboot启动流程-board_init_r函数执行过程

一. uboot启动流程 本文来了解 board_init_r 函数执行过程。_main函数会调用到 board_init_r 函数。 二. board_init_r函数执行过程 _main 函数会调用到 board_init_r 函数。 _main 函数在 uboot的 /arch/arm/lib/crt0.S 文件中。_main函数中&#xff0c;执行完 relocate_…

JAVA毕业设计098—基于Java+Springboot的在线教育课程视频(源码+数据库)

基于JavaSpringboot的在线教育课程视频(源码数据库)098 一、系统介绍 本系统分为管理员、教师、用户三种角色(角色菜单可自行分配) 用户功能&#xff1a; 注册、登录、课程搜索、视频观看、课程资料发布、资料浏览、用户中心、我的发布、通知信息、密码修改 教师功能&…

IP 子网划分(VLSM)

目录 一、 为什么要划分子网 二、如何划分子网 1、划分两个子网 2、划分多个子网 一、 为什么要划分子网 假设有一个B类IP地址172.16.0.0&#xff0c;B类IP的默认子网掩码是 255.255.0.0&#xff0c;那么该网段内IP的变化范围为 172.16.0.0 ~ 172.16.255.255&#xff0c;即…

【SpringCloud】Eureka原理分析、搭建Eureka服务、服务注册、服务发现

&#x1f40c;个人主页&#xff1a; &#x1f40c; 叶落闲庭 &#x1f4a8;我的专栏&#xff1a;&#x1f4a8; c语言 数据结构 javaEE 操作系统 Redis 石可破也&#xff0c;而不可夺坚&#xff1b;丹可磨也&#xff0c;而不可夺赤。 eureka 一、Eureka原理分析1.1 服务调用出现…