继承与组合

【一】什么是继承

  • 继承就是创建新类的一种方式,这个新类可以继承一个或者多个其他类的属性

  • 新的类如果有自己属性,那就叫派生

【二】继承的优点

  • 可以继承父类的所有属性和方法,这样就可以实现代码去重。

【三】继承方式

  • 单继承:继承一个父类的子类

  • 多继承:继承多个父类的子类

例如:

class Student(School):
# 被继承的类叫父类 School
# 新类就叫子类  Student

【四】单继承

class Person(object):
    height = 180
    weight = 60
​
# 继承Person
class Student(Person):
    def __init__(self, name):
        self.name = name
​
    def tell_me(self):
        print(f"我是{self.name},我的身高是{self.height},我的体重是{self.weight}")
​
​
stu1 = Student("knight")
stu1.tell_me()

【五】多继承

class Person(object):
    height = 180
    weight = 60
​
​
class School(object):
    school_name = '家里蹲'
​
# 继承两个父类,Person和School
class Teacher(Person,School):
    def __init__(self, name):
        self.name = name
​
    def tell_me(self):
        print(f"我是{self.name},我所在的学校是{self.school_name},我的身高是{self.height},我的体重是{self.weight}")
​
​
tea1 = Teacher("knight")
tea1.tell_me()

【六】查看当前继承的父类状况

# base 只打印一个当前继承的父类,如果当前继承了多个,那么默认打印第一个
# base 打印所有当前继承的父类
​
print(Student.__base__)     # 只继承了一个父类,只能查看到一个父类
print(Teacher.__base__)     # 虽然继承了两个父类,但也只能查看到从左往右第一个父类
​
print(Student.__bases__)    # 只继承了一个父类,可以查看所有继承的父类
print(Teacher.__bases__)    # 继承了两个父类,也可以查看所有继承的父类

【七】经典类和新式类

# 经典类和新式类的区别在于Python版本的不同
# 在 py3 版本之前存在两个概念 ,在之后就没有经典类的概念了,只有新式类
# 【一】什么是经典类
# 在py2中没有显示继承 object 的类或者是该类的子类都是经典类
# 【二】什么是新式类
# 在py2中显示继承 object 的类或者是该类的子类都是新式类
# 在py3之后所有的类默认都是新式类,不写m默认继承 object

【八】继承和抽象

  • 继承是由少变多

  • 抽象是由多变少

# 【1】没有继承和抽象
class Cat(object):
    def speak(self):
        print(f"喵喵叫")
​
    def eat(self):
        print(f"猫可以吃饭")
​
    def drink(self):
        print(f"猫可以喝水")
​
​
class Dog(object):
    def speak(self):
        print(f"汪汪叫")
​
    def eat(self):
        print(f"狗可以吃饭")
​
    def drink(self):
        print(f"狗可以喝水")
​
​
cat_one = Cat()
print(cat_one.speak())
dog_one = Dog()
print(dog_one.speak())
# 【使用抽象和继承】
    # 先抽象
class Animal(object):
    def speak(self):
        print(f"{self.name}可以叫")
    def eat(self):
        print(f"{self.name}可以吃饭")
    def drink(self):
        print(f"{self.name}可以喝水")
​
    # 再继承
class Cat(Animal):
    def __init__(self,name):
        self.name = '猫'+name
​
class Dog(Animal):
    def __init__(self,name):
        self.name = '狗'+name
​
cat_one = Cat(name='小花')
print(cat_one.speak())          # 猫小花可以叫
dog_one = Dog(name='小黑')
print(dog_one.eat())            # 狗小黑可以吃饭

【九】不封装与封装的属性查找顺序

  • 无封装时继承(通过谁实例化得到的对象就优先去谁里面找)

class Foo:
    def f1(self):
        print('Foo.f1')
​
    # 【四】在父类 Foo 里面找到了 f2
    def f2(self):
        # 【五】打印 Foo.f2
        print('Foo.f2')
        # 【六】self.f1
        self.f1()
​
​
class Bar(Foo):
    # 【七】因为是 通过Bar实例化得到的对象,所以 self 就是 Bar
    def f1(self):
        # 【八】打印 Bar.f1
        print('Bar.f1')
    # 【三】Bar里面没有f2,去父类找 Foo
​
​
# 【一】类实例化得到对象
b = Bar()
# 【二】对象调用方法 f2
b.f2()
# Foo.f2
# Bar.f1
  • 有封装时继承(变形之后,就只能在当前自己的类中找)

class Foo:
    def __f1(self):
        print('Foo.f1')

    # 【四】在父类 Foo 里面找到了 f2
    def f2(self):
        # 【五】打印 Foo.f2
        print('Foo.f2')
        # 【六】self.__f1
        # 没有变形时self 是谁就去谁里面找
        # 变形之后,就只能在当前自己的类中找
        self.__f1()


class Bar(Foo):
    def __f1(self):
        # 【八】打印 Bar.f1
        print('Bar.f1')
    # 【三】Bar里面没有f2,去父类找 Foo


# 【一】类实例化得到对象
b = Bar()
# 【二】对象调用方法 f2
b.f2()
# Foo.f2
# Foo.f1
【小总结】
  • 如果属性不封的情况下,谁实例化得到的self 就去谁里面找

  • 如果属性封装的情况下 ,谁实例化得到的self 无效,只能在当前所在的类的名称空间里面找

【十】菱形结构继承顺序

  • 在py2中分为深度优先和广度优先

  • 在py3中只有广度优先

【1】深度优先
  • 深度优先发生在经典类上,当前类内部找不到指定属性时,会向上找

  • 一条线找到黑

【2】广度优先
  • 广度优先发生在新式类上,在当前类内部找不到指定属性时,会向上找

  • 顺序是广度优先

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):
    def test(self):
        print('from D')


class E(C):
    def test(self):
        print('from E')


class F(D, E):
    # def test(self):
    #     print('from F')
    pass


f1 = F()
f1.test()

# 新式类继承顺序:F->D->B->E->C->A
# 经典类继承顺序:F->D->B->A->E->C
  • 只有新式才有这个属性可以查看线性列表,经典类没有这个属性

print(F.__mro__)

【十一】派生

  • 派生是指,子类继承父类,派生出自己的属性与方法,并且重用父类的属性与方法

【1】子类继承父类的属性
class People:
    school = '北大'

    def __init__(self,name,sex,age):
        self.name = name
        self.sex = sex
        self.age = age

class Teacher(People):
    # 派生:派生出自己新的属性,在进行属性查找时,子类的属性会优先于父类被查找到
    def __init__(self,name,sex,age,title):
        self.name = name
        self.sex = sex
        self.age = age
        self.title = title
    def teach(self):
        print('%s is teaching' % self.name)
#
# 只会找自己类中的__init__,并不会自动调用父类中的
obj = Teacher('knight','male',18,'教授')
print(obj.teach(),obj.name,obj.sex,obj.age,obj.title,)
# knight is teaching
# None
# knight male 18 教授
【2】继承方式一
class People:
    school = '清华大学'

    def __init__(self, name, sex, age):
        self.name = name
        self.sex = sex
        self.age = age

class Teacher(People):
    # 派生:派生出自己新的属性,在进行属性查找时,子类的属性会优先于父类被查找到
    def __init__(self,name,sex,age,title):
        # 直接调用 父类 中 的 __init__ 方法
        # 调用的是函数,因而需要传入self
        People.__init__(self,name,sex,age)
        self.title = title

    def teach(self):
        print('%s is teaching' % self.name)


# 只会找自己类中的__init__,并不会自动调用父类的
obj = Teacher('knight','male',18,'叫兽')
print(obj.name,obj.sex,obj.age,obj.title)
【3】继承方式二
# 调用super()会得到一个特殊的对象
# 该对象专门用来引用父类的属性
# 且严格按照MRO规定的顺序向后查找
class People:
    school = '清华大学'

    def __init__(self, name, sex, age):
        self.name = name
        self.sex = sex
        self.age = age


class Teacher(People):
    # 派生 : 派生出自己新的属性,在进行属性查找时,子类中的属性名会优先于父类被查找
    def __init__(self, name, sex, age, title):
        # 直接调用 父类 中 的 __init__ 方法
        # 调用的是绑定方法,因此会自动传入self,但是需要传入相应的参数
        super().__init__(name, sex, age)
        self.title = title

    def teach(self):
        print('% is teaching' % self.name)


# 只会找自己类中的__init__,并不会自动调用父类的
obj = Teacher('knight', 'male', 18, '叫兽')

print(obj.name, obj.sex, obj.age, obj.title)

【十二】组合

在一个类中,以另外一个类的对象作为数据属性,称为类的组合

class Course:
    def __init__(self, name, period, price):
        self.name = name
        self.period = period
        self.price = price

    def tell_info(self):
        print(f'当前课程名字 {self.name} 当前课程周期 {self.period} 当前课程价格 {self.price}')


class Date:
    def __init__(self, year, mon, day):
        self.year = year
        self.mon = mon
        self.day = day

    def tell_birth(self):
        print(f'当前生日 {self.year} 年 {self.mon} 月 {self.day} 日')


class People:
    school = '清华大学'

    def __init__(self, name, sex, age,title):
        self.name = name
        self.sex = sex
        self.age = age
        self.title = title
    def tell_school_info(self):
        print(f"{self.name}在{self.school}工作")

# Teacher类基于继承来重用People代码
# 基于组合来重用Date类和Course类的代码
class Teacher(People):
    def __init__(self, name, sex, age, title, year, mon, day):
        super().__init__(name, age, sex,title)
        # 老师有生日
        self.birth = Date(year, mon, day)
        # 老师有课程,可以在实例化后,往该列表添加Course类的对象
        self.courses = []

    def teach(self):
        print(f"老师正在授课{self.name},目前是{self.title}")


python = Course('python', '3mons', 3000)
linux = Course('linux', '2mons', 2000)
teacher1 = Teacher('knight', 'male', 18, 'NB', 2002, 6, 3)

# teacher1有两门课程
teacher1.courses.append(python)
teacher1.courses.append(linux)

# 重用Data类的功能
teacher1.birth.tell_birth()
teacher1.tell_school_info()
teacher1.teach()
# 重用Course类的功能
for obj in teacher1.courses:
    obj.tell_info()
    
# 当前生日 2002 年 6 月 3 日
# knight在清华大学工作
# 老师正在授课knight,目前是NB
# 当前课程名字 python 当前课程周期 3mons 当前课程价格 3000
# 当前课程名字 linux 当前课程周期 2mons 当前课程价格 2000

【十三】组合与继承的区别

  • 组合与继承都是有效地利用已有类的资源的重要方式。但是二者的概念和使用场景皆不同

【1】继承的方式
  • 通过继承建立了派生类与基类之间的关系,它是一种'是'的关系,比如白马是马,人是动物

  • 当类之间有很多相同的功能,提取这些共同的功能做成基类,用继承比较好,比如老师是人,学生是人

【2】组合的方式
  • 用组合的方式建立了类与组合的类之间的关系,它是一种‘有’的关系,比如教授有生日,教授教python和linux课程,教授有学生s1、s2、s3..

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

memory consistency

memory consistency model 定义了对于programmer和implementor来说,访问shared memory system的行为; 对于programmer而言,他知道期望值是什么, 知道会返回什么样的数据;; 对于implementro而言,…

数据结构——链表专题1

文章目录 一、移除链表元素二、反转链表三、合并两个有序链表四、链表的中间节点五、环形链表的约瑟夫问题六、分割链表 一、移除链表元素 原题链接:移除链表元素 一个解法是遍历原链表,将与val相等的结点抛弃,链接后一个结点 另一个解法是…

corefBERT论文阅读

CorefBERT是清华大学团队发表的,继SpanBERT之后另一针对共指消解的BERT模型。共指消解任务对于文本理解、智能问答等其他NLP子任务起到至关重要的作用。 为了提高语言模型的共指推理能力,一个简单的解决方案是使用有监督的共指解析数据在bert等模型进行…

论文笔记ColdDTA:利用数据增强和基于注意力的特征融合进行药物靶标结合亲和力预测

ColdDTA发表在Computers in Biology and Medicine 的一篇一区文章 突出 • 数据增强和基于注意力的特征融合用于药物靶点结合亲和力预测。 • 与其他方法相比,它在 Davis、KIBA 和 BindingDB 数据集上显示出竞争性能。 • 可视化模型权重可以获得可解释的见解。 …

Linux网络部分——DNS域名解析服务

目录 1. 域名结构 2. 系统根据域名查找IP地址的过程 3.DNS域名解析方式 4.DNS域名解析的工作原理【☆】 5.域名解析查询方式 6.搭建主从DNS域名服务器 ①初始化操作主服务器和从服务器,安装BIND软件 ②修改主服务器的主配置文件、区域配置文件、区域数…

【c1】数据类型,运算符/循环,数组/指针,结构体,main参数,static/extern,typedef

文章目录 1.数据类型:编译器(compiler)与解释器(interpreter),中文里的汉字和标点符号是两个字节,不能算一个字符(单引号)2.运算符/循环:sizeof/size_t3.数组…

基于java的CRM客户关系管理系统的设计与实现(论文 + 源码 )

【免费】基于Java的CRM客户关系管理系统的设计和实现.zip资源-CSDN文库https://download.csdn.net/download/JW_559/89273409 基于Java的CRM客户关系管理系统的设计与实现 摘 要 随着互联网的高速发展,市场经济的信息化,让企业之间的竞争变得&#xff0…

复写零(双指针)

下面的解法需要手动画图,举例去体会,只有自己手动去做了,才会有所收获。 class Solution {public void duplicateZeros(int[] arr) {int n arr.length;//先找到最后一个元素的位置;//至于为什么要直接先设dest 为-1,这是经过研究…

CNN笔记详解

CNN(卷积神经网络) 计算机视觉,当你们听到这一概念的是否好奇计算机到底是怎样知道这个图片是什么的呢?为此提出了卷积神经网络,通过卷积神经网络,计算机就可以识别出图片中的特征,从而识别出图片中的物体。看到这里充…

分布式与一致性协议之ZAB协议(四)

ZAB协议 ZooKeeper是如何选举领导者的。 首先我们来看看ZooKeeper是如何实现成员身份的? 在ZooKeeper中,成员状态是在QuorumPeer.java中实现的,为枚举型变量 public enum ServerState { LOOKING, FOLLOWING, LEADING, OBSERVING }其实&…

为何美国多IP服务器是全自动内容采集站的最佳选择?

为何美国多IP服务器是全自动内容采集站的最佳选择? 在建设全自动内容采集站时,选择合适的服务器至关重要。而在众多选项中,美国多IP服务器被认为是最佳选择,究竟为何呢?本文将从多个方面进行深入探讨。 为何美国多IP服务器是全自动内容采集…

分享8000网剧资源

兄弟们,前段时间搞短剧,收集了8500多部网剧资源。搞了整整两个月就赚3块两毛八,电费都不够。还不如进厂打螺丝。果断放弃这项目。 资源在手里面也没啥用。分享出来,大家看着玩。 有其他好的网络项目也可以分享分享。也可也一起…

真希望我父母读过这本书的笔记(二)

系列文章目录 真希望我父母读过这本书的笔记(一) 真希望我父母读过这本书的笔记(二) 文章目录 系列文章目录PART 5 培养心理健康的孩子亲子关系决定心理健康互动及来回交流如何开始交流互看游戏交流恐惧症 若遇棘手之际&#xff0…

9.Admin后台系统

9. Admin后台系统 Admin后台系统也称为网站后台管理系统, 主要对网站的信息进行管理, 如文字, 图片, 影音和其他日常使用的文件的发布, 更新, 删除等操作, 也包括功能信息的统计和管理, 如用户信息, 订单信息和访客信息等. 简单来说, 它是对网站数据库和文件进行快速操作和管…

[Flutter]创建一个私有包并使用

在Flutter中创建一个自己的私有组件(通常称为包或库),并通过Dart的包管理工具pub进行使用。 一、创建一个新的Flutter包 1.使用命令行创建 使用Flutter命令行工具来创建一个新的包: $ flutter create --templatepackage my_pri…

嵌入式复习重点

嵌入式系统有多种表现形式,包括计算机MCU、SOC片上系统、SOPC片上系统、GPU和FPGA等。 MCU(微控制器): 是最基本也是最常见的嵌入式系统形式,是集成了CPU、ROM、RAM、IO口、定时器、中断控制器等组件的单一芯片。MCU广泛用于电器电子产品的控制。SoC(系统片上芯片):…

P8800 [蓝桥杯 2022 国 B] 卡牌

P8800 [蓝桥杯 2022 国 B] 卡牌 分析 “最多” -- 二分 1.二分区间(凑齐的卡牌套数): l:a[]min;r:(a[]b[])max 2.check(x): (1)for循环内: 判断x - a[i…

Enhancing Diffusion——利用三维透视几何约束增强扩散模型

概述 透视在艺术中被广泛研究,但现代高质量图像生成方法却缺乏透视精度。新的生成模型引入了几何约束,通过训练过程提高透视精度。这样可以生成更逼真的图像,并提高相关深度估计模型的性能。 最近的图像生成技术使研究人员能够创造性地进行…

茅台葡萄酒打出节日新式营销“组合拳”,两月内落地品鉴会超千桌

执笔 | 尼 奥 编辑 | 古利特 2024年1-3月酒类进出口数据显示,葡萄酒进口量微增3.66%,进口额同比下滑11%,一季度整体跌势大缓,逐步走出普遍低迷的行情。与之相反的是,作为国产葡萄酒代表的茅台葡萄酒继续保持向上的战…

【C++】 认识多态 + 多态的构成条件详细讲解

前言 C 目录 1. 多态的概念2 多态的定义及实现2 .1 虚函数:2 .2 虚函数的重写:2 .2.1 虚函数重写的两个例外: 2 .3 多态的两个条件(重点)2 .4 析构函数为啥写成虚函数 3 新增的两个关键字3.1 final的使用:3…
最新文章