python学习笔记-09

面向对象编程-中

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

封装:把内容封装起来便于后面的使用。对于封装来讲,就是使用__init__方法将内容封装道对象中,然后通过对象直接或者self获取被封装的内容。

继承:子继承父的属性和方法。

多态:所谓多态就是定义时的类型和运行时的类型不一样,同一种行为对于不同的子类对象有不同的行为表现。python不支持Java和C#这一类强类型语言中多态的写法,但是原生多态,“鸭子类型”。

鸭子类型:在程序设计中,鸭子类型是动态类型的一种风格。在这种风格中,一个对象有效的语义,不是由继承自特定的类或实现特定的接口,而是由当前方法和属性的集合决定。
鸭子测试:当看到一只鸟走起来像鸭子、游泳像鸭子、叫起来也像鸭子,那么这只鸟就可以被称为鸭子。
在鸭子类型中,关注的不是对象的类型本身,而是它是如何使用的。

1.析构函数

析构方法:当一个对象被删除或者被销毁时,python解释器也会默认调用一个方法,这个方法为__del__()方法,也成为析构方法。

一般来讲程序执行结束自动调用此方法。

#析构方法
class Animal:def __init__(self,name):self.name=nameprint('init方法调用,初始化%s对象'%(self.name))passdef __del__(self):print('del方法调用,释放%s内存空间'%(self.name))passpass
cat=Animal('猫')
print('=================')
dog=Animal('柯基')
#由此可看,是当函数彻底执行结束后才释放所有内存空间

在这里插入图片描述
除此之外,对象被删除的时候也会调用析构方法。

#析构方法
class Animal:def __init__(self,name):self.name=nameprint('init方法调用,初始化%s对象'%(self.name))passdef __del__(self):print('del方法调用,释放%s内存空间'%(self.name))passpass
cat=Animal('猫')
del cat   #手动删除对象,执行__del__方法
print('=================')
dog=Animal('柯基')

在这里插入图片描述
析构方法主要是用于释放空间,释放后对象就不能再使用。

总结:
当整个程序脚本执行完毕后会自动调用__del__方法
当对象被手动销毁时也会自动调用__del__方法
析构函数一般用于资源回收,利用__del__方法销毁对象回收内存等资源

2.继承

2.1 单继承

#单继承
#父类:
class Animal:def eat(self):'''父类方法:return:'''print('吃')passdef drink(self):'''父类方法:return:'''print('喝')passpass
#子类
class Dog(Animal):   #继承Animaldef wwj(self):'''子类独有的方法:return:'''print('小狗汪汪叫')pass
class Cat(Animal):def mmj(self):'''子类独有的方法:return:'''print('小猫喵喵叫')passpass
d1=Dog()
d1.eat()
c1=Cat()
c1.drink()

在这里插入图片描述

对于面向对象的继承来说,其实就是将多个类共有的方法提取到父类中,子类仅需继承父类而不必一一实现每个方法,极大提高效率,精简代码,便于扩展。

单继承的语法:
class 子类名(父类名):.......

2.2 多继承
子类可以继承多个父类,同时拥有多个父类的公共方法。

#多继承
#父类1
class God:def fly(self):print('神都会飞')passpass
#父类2
class Monkey:def eat(self):print('猴子都吃桃子')passpass
#子类
class Swk(God,Monkey):   #多继承def chan(self):print('孙悟空会七十二变')passpass
s=Swk()
s.chan()
s.fly()
s.eat()

在这里插入图片描述
当多个父类中存在相同的方法时,一层层向上找,就近原则使用。

class D(object):def eat(self):print('D.eat')passpass
class C(D):def eat(self):print('C.eat')passpass
class B(D):pass
class A(B,C):pass
a=A()
a.eat()
print(A.__mro__)  #可以显示类的依次继承关系

在这里插入图片描述
2.3 继承的传递
孙-子-父

class Grandfather:def eat(self):print('爷爷的吃')passpass
class Father(Grandfather):pass
class Son(Father):pass
s=Son()
print(Son.__mro__)
s.eat()  #此方法是从父类的父类继承过来的
#在类的传递过程中,我们把父类称为基类,子类称为派生类,父类的属性喝方法可以一级一级的传到子类,多少级都可以

在这里插入图片描述

3.重写父类方法

所谓重写就是在子类中有一个和父类相同名字的方法,在子类中的方法会覆盖掉父类中同名的方法,实际上也就是上述的“就近原则”,这种重写的方法中父类子类的变量什么的都是不互通的。

但如果一味的重写会使父类继承失去意义,因此如果在子类中重写时可以调用父类方法,提高代码效率。

4.调用父类方法

class Dog:def __init__(self,name,color):self.name=nameself.color=colorpassdef bark(self):print('叫')passpass
class keji(Dog):def __init__(self,name,color):Dog.__init__(self,name,color)   #法一:手动调用调用父类的方法,执行完毕就可以具备name,color这两个实例属性了super().__init__(name,color)     #法二:也可以这样调用super是自动找到父类进而调用方法,如果有多个父类会逐一的找直到找到为止self.height=20  #如果想要除了父类中的属性之外的属性可以声明passdef bark(self):super().bark()print('柯基叫')print(self.name)passdef __str__(self):return '{}的颜色是{},它的身高是{}'.format(self.name,self.color,self.height)pass
kj=keji('柯基','黄')
kj.bark()
print(kj )

在这里插入图片描述

注:
super()自动调用和手动调用写一个就行

5.多态

要想实现多态必须遵守两个前提:
1.继承:多态必须发生在父类和子类之间
2.重写:子类必须要重写父类的方法
#多态
class Animal:def speak(self):print('我是')pass
class Duck(Animal):pass
duck=Duck()
duck.speak()
#多态
class Animal:def speak(self):print('我是')pass
class Duck(Animal):def speak(self):print('我是一个鸭子')pass
duck=Duck()
duck.speak()

在这里插入图片描述
在这里插入图片描述
以上就是一种多态的体现,同样是duck.speak,输出两个不一样的结果。
法一:

#多态
class Animal:def speak(self):print('我是')pass
class Duck(Animal):def speak(self):print('我是一个鸭子')pass
duck=Duck()
duck.speak()
class Dog(Animal):def speak(self):print('我是一只小狗')passpass
dog=Dog()
dog.speak()

法二:

#多态
class Animal:def speak(self):print('我是')pass
class Duck(Animal):def speak(self):print('我是一个鸭子')pass
class Dog(Animal):def speak(self):print('我是一只小狗')passpass
def commonInvoke(obj):'''统一调用的方法:param obj:对象的实例:return:'''obj.speak()pass
listObj=[Duck(),Dog()]
for i in listObj:'''循环调用函数'''commonInvoke(i)#用一个函数调用

在这里插入图片描述
以上是多态的第二种体现

多态的优点:
增加程序的灵活性
增加程序的扩展性

6.类属性和实例属性

类属性是类对象所拥有的属性,它被所有类对象的实例对象共有,类对象和实例对象可以访问。

实例属性是实例对象所拥有的属性,只能通过实例对象访问

#类属性
class Student:name='黎明'   #类属性def __init__(self,age):self.age=age   #实例属性passpasslm=Student(18)
print(lm.name)    #通过实例对象访问类属性
print(lm.age)
print('------------')
print(Student.name)    #通过类对象访问name
print(Student.age)     #报错是因为age归实例对象所有,不属于类对象
#只有类属性可以被类对象和实例对象共同访问
#实例属性只能由实例对象访问

在这里插入图片描述
所有的实例对象访问的类属性是一个值,实例属性不同。
实例对象对于类属性只有使用的权力,没有修改的权力。

#类属性
class Student:name='黎明'   #类属性def __init__(self,age):self.age=age   #实例属性passpasslm=Student(18)
print(lm.name)    #通过实例对象访问类属性
lm.name='修改'     #重新声明一个值
print(lm.age)
print(lm.name)    #重新声明后改变了自己
print('------------')
xh=Student(22)
print(xh.name)    #重新声明完后并没有改变
print('----------------')
print(Student.name)    #通过类对象访问name

在这里插入图片描述

#类属性
class Student:name='黎明'   #类属性def __init__(self,age):self.age=age   #实例属性passpass
Student.name='change'   #这样可以彻底改变类属性的值
lm=Student(18)
print(lm.name)    #通过实例对象访问类属性   
print(lm.age)
print(lm.name)    #重新声明后改变了自己
print('------------')
xh=Student(22)
print(xh.name)    #重新声明完后并没有改变
print('----------------')
print(Student.name)    #通过类对象访问name

在这里插入图片描述

7. 类方法和静态方法

7.1 类方法
类方法:类对象所拥有的方法,需要用装饰器@classmethod来标识其为类方法,对于类方法,第一个参数必须是类对象,一般以cls作为第一个参数,类方法可以通过类对象、实例对象调用。

#类方法
class People:country='china'@classmethoddef get_country(cls):return cls.country  #访问类属性pass@classmethoddef change_country(cls,data):cls.country=data   #在类方法中修改类属性的值passpass
print(People.get_country()) #通过类对象去引用
p=People()
print(p.get_country())
p.change_country('england')
print(p.get_country())

在这里插入图片描述
7.2 静态方法
类对象所拥有的方法,需要用@staticmethod标识静态方法,静态方法不需要任何参数。

#类方法
class People:country='china'@classmethoddef get_country(cls):return cls.country  #访问类属性pass@classmethoddef change_country(cls,data):cls.country=data   #在类方法中修改类属性的值pass@staticmethoddef getData():return People.countrypasspass
print(People.getData())
p=People()
print(p.getData())  #一般情况下,我们不会通过实例对象访问静态方法
#静态方法的逻辑实现和类、实例对象没什么交互,主要用来存放逻辑性代码,一般不会涉及到类中方法和属性的操作。数据资源能够得到充分利用
# 返回当前的系统时间:
import time
class Time:@staticmethoddef showTime():return time.strftime('%H:%M:%S',time.localtime())pass
print(Time.showTime())

7.3 区别

1.类方法的第一个参数是类对象cls,通过cls引用的类对象的属性和方法,用装饰器@classmethod修饰
2.实例方法的第一个参数是实例对象self,通过self引用的可能是类属性,也有可能是实例属性,具体问题具体分析,不过存在相同名称的类属性和实例属性的情况下,实例属性优先级更高。
3.静态方法中不需要额外定义参数,因此在静态方法中引用类属性的化必须通过类对象引用,必须用@staticmethod修饰。

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

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

相关文章

Kubernetes之Deployment详解

如何更好的用好Deployment?本文尝试从Deployment的使用、控制器实现原理及使用规范3方面进行阐述。希望对您有所帮助! 一、Kubernetes Deployment使用浅析 Kubernetes Deployment 是一种高级资源对象,用于声明和管理 Pod 和 ReplicaSet。它…

Java中的字符串操作技巧与最佳实践

Java中的字符串操作技巧与最佳实践 大家好,我是免费搭建查券返利机器人省钱赚佣金就用微赚淘客系统3.0的小编,也是冬天不穿秋裤,天冷也要风度的程序猿!今天,我们将探讨Java中的字符串操作技巧与最佳实践。字符串操作是…

Uniapp在屏幕尺寸低于960出现样式错乱(开箱即用)

我司项目突然要做平板兼容,我在调试的时候发现当屏幕尺寸低于960px发现样式但凡是以rpx单位的全部失效,如果是以px为单位那么影响就比较小,当时解决方案是写了不少媒体查询和把单位rpx改成px,后面查阅文档发现大错特错宽屏适配只需一行代码即…

代码随想录算法训练营:12/60

非科班学习算法day12 | LeetCode150:逆波兰表达式 ,Leetcode239: 滑动窗口最大值 目录 介绍 一、基础概念补充: 1.c字符串转为数字 1. std::stoi, std::stol, std::stoll, std::stoul, std::stoull(最常用) 2. std::strings…

Python高级编程:机器学习基础

Python高级编程:机器学习基础 在前几篇文章中,我们探讨了Python的基础语法、面向对象编程、标准库、第三方库、并发编程、异步编程、网络编程与网络爬虫、数据库操作与ORM以及数据分析与数据可视化。在这篇文章中,我们将深入探讨Python在机器学习领域的应用。机器学习是人工…

04--MySQL8.0_JDBC

第一章 JDBC概述 之前我们学习了JavaSE,编写了Java程序,数据保存在变量、数组、集合等中,无法持久化,后来学习了IO流可以将数据写入文件,但不方便管理数据以及维护数据的关系; 后来我们学习了数据库管理软件MySQL,可以方便的管理数据1。 那么如何将它俩结合起来呢?即…

《AI旋律:创意产业的重塑与共生》

AI乐章:技术革命下的创意产业新生态 在数字化浪潮的推动下,音乐创作领域迎来了前所未有的变革——AI音乐大模型的横空出世,犹如一颗石子投入平静的湖面,激起了层层涟漪。这些模型以令人难以置信的速度和多样性,将音乐…

学懂C#编程:常用高级技术——学会Lambda表达式的应用

Lambda表达式在C#中是一种简洁且强大的编写代码的方式,它主要用于创建匿名函数,也就是那些没有名字的函数。想象一下,你有时候需要快速写一个小功能,但又不想专门为此定义一个方法,Lambda表达式就是你的救星。下面我用…

【树形dp 换根法 BFS】2581. 统计可能的树根数目

本文涉及知识点 CBFS算法 动态规划汇总 图论知识汇总 树形dp 换根法 BFS LeetCode 2581. 统计可能的树根数目 Alice 有一棵 n 个节点的树,节点编号为 0 到 n - 1 。树用一个长度为 n - 1 的二维整数数组 edges 表示,其中 edges[i] [ai, bi] &#xf…

linux的source命令

用法 source file 也可以用.空格file来代替 . file 作用 在当前bash环境下读取并执行FileName中的命令. source(或点)令通常用于重新执行刚修改的初始化文档,如 .bash_profile 和 .profile等配置文件. 简单的说就是: source命令会把file里的命令在当前shell里一…

《书生·浦语大模型实战营》第5课 学习笔记:LMDeploy 量化部署 LLM 实践

文章大纲 0.背景知识与简介计算机组成原理:变量的存储参数量与推理的关系 1.LMDeploy环境部署1.1 创建开发机1.2 创建conda环境InternStudio开发机创建conda环境(推荐)本地环境创建conda环境 1.3 安装LMDeploy 2.LMDeploy模型对话(chat)2.1 H…

【CSS in Depth2精译】1.2 继承~1.3 特殊值

文章目录 1.2 继承1.3 特殊值1.3.1 inherit 关键字1.3.2 initial 关键字1.3.3 unset 关键字1.3.4 revert 关键字 1.2 继承 除了层叠,还有一种给元素设置样式的方式:继承。经常有人把层叠与继承的概念弄混淆。它们虽然有关联,但也应该分辨清楚…

优化堆排序

优化堆排序 堆排序是一种基于比较的排序算法,它利用堆这种数据结构来进行排序。堆是一个近似完全二叉树的结构,并同时满足堆积的性质:即子节点的键值或索引总是小于(或者大于)它的父节点。堆排序算法分为两个大的步骤:首先将待排序的序列构造成一个最大堆,此时,整个序…

在Linux/Ubuntu/Debian中使用 `tee` 命令将输出显示在终端并写入文件中

在Linux/Ubuntu/Debian中使用 tee 命令将输出显示在终端并写入文件中 在日常的 Linux 系统操作中,我们常常需要将命令的输出重定向到文件中以便于后续查看和处理。本文将通过几个常见示例,介绍如何使用 tee 命令来同时将输出显示在终端并写入文件中。 …

通用VS垂直,谁将领跑落地场景?或AI大模型的抉择与探索

随着人工智能技术的飞速发展,大模型已成为业界关注的焦点。在这个竞争激烈的战场中,通用大模型和垂直大模型各自展现出不同的优势,引发了业界的广泛讨论。那么,对于大模型的第一个赛点,你更青睐哪一方呢? …

创新实训(十二) 项目开发——历史对话增加查询功能

必要性 随着对话记录的增加,根据对话名称conv_name查询对话对用户来说非常有必要实现。 实现 原来的history_chats.vue中使用了getChatList() 在onMounted时直接获取用户的所有对话记录,如果要实现查询功能,需要增加两个变量: …

【STM32入门学习】基于DHT20温湿度传感器数据采集和显示

目录 一、软件I2C和硬件I2C 1.1硬件I2C 1.2软件I2C 二、创建工程(基于HAL库) 三、实物连线 3.1DHT20 3.2串口传输: 四、结果演示 4.1部署文件 4.2主要代码分析 五、心得体会 一、软件I2C和硬件I2C I2C 基本读写过程: 其中S表示由主…

Android Basis - Google Keybox

什么是Keybox Android O 开始谷歌要求每台机器预制谷歌提供的 Attestion Key的需求,该需求要求,每台机器都预制谷歌提供的 key,因此需要 oem 厂商在工厂完成预制。没有预制该key 将直接导致机器 cts 相关测试项失败。Google attestation key的集合又称作…

Spring AI 介绍以及与 Spring Boot 项目整合

Spring AI 项目旨在简化使用 Spring Boot 开发包含人工智能功能的应用程序,提供抽象和支持多种模型提供商及矢量数据库提供商。 Spring AI 的功能特点 支持主流模型提供商:如 OpenAI、Microsoft、Amazon、Google 和 Huggingface 等。支持多种模型类型&a…