【Python学习】面向对象

embedded/2024/9/24 12:18:59/

面向对象

  • 1.初识对象
    • 1.1 生活中数据的组织
    • 1. 2 程序中数据的组织
    • 1.3 使用对象组织数据
    • 1.4进行对比
  • 2. 成员方法
    • 2.1 类的定义和使用
    • 2.2 成员变量和成员方法
      • 2.2.1 成员变量
      • 2.2.2 成员方法的定义语法
      • 2.2.3 self 的作用
  • 3. 类和对象
    • 3.1 面向过程
    • 3.2 面向对象
  • 4.构造方法
    • 4.1 属性成员变量的赋值
  • 5. 其他内置方法
  • 6. 封装
    • 6.1 **面向对象的三大特性**
    • 6.2 封装
    • 6.3 私有成员
    • 6.4 使用私有成员
  • 7.继承
    • 7.1 单继承
    • 7.2 多继承
    • 7.3 复写父类成员
    • 7.4 调用父类同名成员
  • 8. 类型注解
    • 8.1 变量类型注解
  • 语法一: **变量名 : 类型**
  • 语法二: type: 类型
  • 类型注解的限制
    • 8.2 函数和方法的形参类型注解:
    • 8.3 Union类型
  • 9. 多态
    • 9.1 多态
    • 9.2 抽象类(接口)
    • 9.3 抽象类的作用

1.初识对象

1.1 生活中数据的组织

比如,我们要统计学生的信息
在这里插入图片描述

1. 2 程序中数据的组织

python">student_1 = {"学号" : "111","姓名" : "张三","性别" : "男","年龄" : "19"
}student_2 = {"学号" : "222","姓名" : "李四","性别" : "男","年龄" : "18"
}
#......# 每次都要重复创建字典

思考:
没次的操作都是重复的

如果程序中也和生活中一样
• 可以设计表格
• 可以将设计的表格打印出来
• 可以将打印好的表格供人填写内容
那么数据的组织就非常方便了。

1.3 使用对象组织数据

在程序中是可以做到和生活中那样,设计表格、生产表格、填写表格的组织形式的。

  1. 在程序中设计表格,我们称之为:设计类( class )
python">class Student:
#这些定义的变量成为成员变量#记录年龄id = None#记录性别name = None#记录性别sex = None#记录年龄age = None
  1. 在程序中打印生产表格,我们称之为:创建对象
python">#使用上述创建的类来创建对象student_1 = Student()student_2 = Student()#数据怎么填入呢?
  1. 在程序中填写表格,我们称之为:对象属性赋值
python"># 对student_1 赋值
student_1.id = "111"
student_1.name = "张三"
student_1.sex = "男"
student_1.age = 19# 对student_2 赋值
student_2.id = "222"
student_2.name = "李四"
student_2.sex = "男"
student_2.age = 18

1.4进行对比

在程序中:

设计表格,称之为:设计类(class)
打印表格,称之为:创建对象
填写表格,称之为:对象属性赋值

2. 成员方法

2.1 类的定义和使用

在上一节中,我们简单了解到可以使用类去封装属性,并基于类创建出一个个的对象来使用。
现在我们来看看类的使用语法:
在这里插入图片描述

2.2 成员变量和成员方法

2.2.1 成员变量

python">class Student:#成员变量 年龄id = None#成员变量 性别name = None#成员变量 别sex = None#成员变量 年龄age = None#成员方法  self必填def Print(self):print(f"学号{self.id}, 姓名{self.name}, 性别{self.sex}, 年龄{self.age}")

可以看出,类中:
不仅可以定义属性用来记录数据也可以定义函数,用来记录行为

其中:
类中定义的属性(变量),我们称之为:成员变量
类中定义的行为(函数),我们称之为:成员方法

2.2.2 成员方法的定义语法

在类中定义成员方法和定义函数基本一致,但仍有细微区别:

python">#只是多加一个self, 其余参数和往常函数一样
def Fun(self, 形参1....,形参N):#方法体

可以看到,在方法定义的参数列表中,有一个:self关键字
self关键字是成员方法定义的时候,必须填写的。它用来表示类对象自身的意思。当我们使用类对象调用方法的是,self会自动被python传入在方法内部,想要访问类的成员变量,必须使用self

2.2.3 self 的作用

注意:

  • self关键字,尽管在参数列表中,但是传参的时候可以忽略它。
  • 表示类对象本身的意思
  • 只有通过self,成员方法才能访问类的成员变量
  • self出现在形参列表中,但是不占用参数位置,无需理会
python">class Student:#成员变量 年龄id = None#成员变量 姓名name = None#成员变量 性别sex = None#成员变量 年龄age = None#成员方法def Print(self):print(f"学号{self.id}, 姓名{self.name}, 性别{self.sex}, 年龄{self.age}")#创建一个对象
student_1 = Student()# 对student_1 赋值
student_1.id = "111"
student_1.name = "张三"
student_1.sex = "男"
student_1.age = 19#不需要传参 self
student_1.Print()

3. 类和对象

3.1 面向过程

C语言是面向过程的,关注的是过程,分析出求解问题的步骤,通过函数调用逐步解决问题。

拿做饭举例:
在这里插入图片描述
在这里插入图片描述

3.2 面向对象

Python是面向对象的,关注的是对象将一件事情拆分成不同的对象,靠对象之间的交互完成。
在这里插入图片描述
上述过程一共有四个对象:人,菜, 锅,火
整个主要过程是:人,菜, 锅,火 四个对象交互完成的,人不需要关注机器人是怎么洗菜,开火的
在这里插入图片描述

4.构造方法

4.1 属性成员变量的赋值

python">#创建一个对象
student_1 = Student()# 对student_1 赋值
student_1.id = "111"
student_1.name = "张三"
student_1.sex = "男"
student_1.age = 19

上面代码中,为对象的属性赋值需要依次进行,略显繁琐。
有没有更加高效的方式,能够一行代码就完成呢?

答:当然可以

  • Python类可以使用:init()方法,称之为构造方法。
  • init 两旁是 两个下划线 " _ "
  • 构造方法也是成员方法,不要忘记在参数列表中提供:self

可以实现:

  1. 在创建类对象(构造类)的时候,会自动执行
  2. 在创建类对象(构造类)的时候,将传入参数自动传递给__init__方法使用
python">class Student:# 成员变量可以省略不写#成员变量 年龄id = None#成员变量 姓名name = None#成员变量 性别sex = None#成员变量 年龄age = None# 构造方法def __init__(self,id , name, sex, age):self.id = idself.name = nameself.sex = sexself.age = age#成员方法def Print(self):print(f"学号{self.id}, 姓名{self.name}, 性别{self.sex}, 年龄{self.age}")#创建对象,同时赋值
student_1 = Student("111", "张三", "男", 19)student_2 = Student("222", "李四", "男", 18)
  • 在构造方法内定义成员变量,需要使用self关键字
python">  # 构造方法def __init__(self,id , name, sex, age):self.id = id  #成员变量 年龄self.name = name  #成员变量 姓名self.sex = sex   #成员变量 性别self.age = age   #成员变量 年龄

这是因为:变量是定义在构造方法内部,如果要成为成员变量,需要用self来表示。

5. 其他内置方法

上文学习的__init__ 构造方法,是Python类内置的方法之一。
这些内置的类方法,各自有各自特殊的功能,这些内置方法我们称之为:魔术方法
在这里插入图片描述

python">class Student:# 构造方法def __init__(self,id , name, sex, age):self.id = id  #成员变量 年龄self.name = name  #成员变量 姓名self.sex = sex   #成员变量 性别self.age = age   #成员变量 年龄# 返回f"学号{self.id}, 姓名{self.name}, 性别{self.sex}, 年龄{self.age}字符串def __str__(self):return f"学号{self.id}, 姓名{self.name}, 性别{self.sex}, 年龄{self.age}"# 年龄大于、小于比较def __lt__(self,other):return self.age < other.age# 年龄大于等于、小于等于比较def __le__(self,other):return self.age <= other.age# 年龄等于比较def __eq__(self,other):return self.age == other.age#创建对象,同时赋值
student_1 = Student("111", "张三", "男", 19)student_2 = Student("222", "李四", "男", 18)# 自动调用__str__(self)
#不实现__str__ 打印的是地址
print(student_1)
print(student_2)# 自动调用__lt__(self,other)
#不实现__lt__ 比较的是地址
print(student_1 < student_2)# 自动调用__le__(self,other)
#不实现__le__ 比较的是地址
print(student_1 >= student_2)# 自动调用__eq__(self,other)
#不实现__eq__ 比较的是地址
print(student_1 == student_2)

6. 封装

6.1 面向对象的三大特性

面向对象编程,是许多编程语言都支持的一种编程思想。

简单理解是:基于模板(类)去创建实体(对象),使用对象完成功能开发。

面向对象包含3大主要特性:

  1. 封装
  2. 继承
  3. 多态

6.2 封装

封装表示的是,将现实世界事物的:
属性
行为

封装到类中,描述为:
成员变量
成员方法

从而完成程序对现实世界事物的描述

在这里插入图片描述

6.3 私有成员

  • 什么是私有成员?
  • 答:现实事物有部分属性和行为是不公开对使用者开放的。同样在类中描述属性和方法的时候也需要达到这个要求,就需要定义私有成员了。私有成员只能在成员方法内使用

类中提供了私有成员的形式来支持:
1.私有成员变量
2.私有成员方法

定义私有成员的方式非常简单,只需要:
1.私有成员变量:变量名以__开头(2个下划线)
2.私有成员方法:方法名以__开头(2个下划线)
3.即可完成私有成员的设置

python">class Student:#私有成员变量__id = None__name = None__sex = None__age = None# 构造方法def __init__(self, id, name, sex, age):self.id = id  # 成员变量 年龄self.name = name  # 成员变量 姓名self.sex = sex  # 成员变量 性别self.age = age  # 成员变量 年龄# 私有成员方法def __Print(self):print(f"学号{self.id}, 姓名{self.name}, 性别{self.sex}, 年龄{self.age}")

6.4 使用私有成员

错误用法:

python">class Student:#私有成员变量__id = None__name = None__sex = None__age = None#这样的构造方法是错误的# 私有变量无法赋值,也无法获取值,会报错def __init__(self, id, name, sex, age):self.id = id  # 成员变量 年龄self.name = name  # 成员变量 姓名self.sex = sex  # 成员变量 性别self.age = age  # 成员变量 年龄# 私有成员方法def __Print(self):print(f"学号{self.id}, 姓名{self.name}, 性别{self.sex}, 年龄{self.age}")#创建对象,同时赋值
#私有变量无法赋值,也无法获取值,会报错
student= Student("111", "张三", "男", 19)#私有方法无法直接被类对象使用
student.Print()

正确用法:

python">class Test:n =None__m = Nonedef __init__(self,n):self.n = ndef __Print(self):print("私有成员")def Fun(self):# 在成员方法内可以调用私有成员变量self.n = 0# 在成员方法内可以调用私有成员方法print(self.n)self.__Print()test = Test(9)
test.Fun()

7.继承

继承就是一个类,继承另外一个类的成员变量和成员方法
继承表示:将从父类那里继承(复制)来成员变量和成员方法(不含私有)

子类构建的类对象,可以
1.有自己的成员变量和成员方法
2.使用父类的成员变量和成员方法

比如,我们要更新一款软件,更新之后的软件会失去之前的功能吗? 当然不会。更新之后的软件会继承之前的某些功能。

语法:

python">#在括号内填写 父类名
class father(父类1, 父类2,...):#类内容体

7.1 单继承

简单的说就是继承单个类(一个父类)

python">
```python
# 父类
class Father:a = Nonedef Fun_1(self):print("父类")self.a = 1print(self.a)#子类
class Brother(Father):b = Nonedef Fun_2(self):print("子类")self.b = 2#使用父类的成员变量print(Father.a)#使用父类的成员方法 要传参selfFather.Fun_1(self)test = Brother()
#调用自己的成员方法
test.Fun_2()#调用父类的成员方法
test.Fun_1()

7.2 多继承

Python的类之间也支持多继承,即一个类可以继承多个父类

python">class Father_1:def Fun_1(self):print("父类一")class Father_2:def Fun_2(self):print("父类二")class Brother(Father_1, Father_2):def Fun_3(self):print("子类")test = Brother()
# 调用父类一
test.Fun_1()
# 调用父类二
test.Fun_2()
# 调用子类
test.Fun_3()

多个父类中,如果有同名的成员怎么办呢?

答:多个父类中,如果有同名的成员,那么默认以继承顺序(从左到右)为优先级。
即:先继承的保留,后继承的被覆盖

python">class Father_1:def Fun(self):print("父类一")class Father_2:def Fun(self):print("父类二")class Brother(Father_1, Father_2):def Fun_1(self):print("子类")test = Brother()
# 调用父类的成员 ,调用的是父类一
test.Fun()

7.3 复写父类成员

子类继承父类的成员属性和成员方法后,如果对其“不满意”,那么可以进行复写
即:在子类中重新定义同名的属性或方法即可。

一旦复写父类成员,那么类对象调用成员的时候,就会调用复写后的新成员

python">class Father_1:def Fun(self):print("父类一")class Father_2:def Fun(self):print("父类二")class Brother(Father_1, Father_2):def Fun(self):print("子类")test = Brother()
# 调用和父类的一样成员方法 ,调用的是自己的
test.Fun()

7.4 调用父类同名成员

一旦复写父类成员,那么类对象调用成员的时候,就会调用复写后的新成员
如果需要使用被复写的父类的成员,需要特殊的调用方式:

  • 方式1:
    调用父类成员
    使用成员变量:父类名.成员变量
    使用成员方法:父类名.成员方法(self)

  • 方式2:
    使用super()调用父类成员
    使用成员变量:super().成员变量
    使用成员方法:super().成员方法()

只能在子类内调用父类的同名成员。
子类的类对象直接调用 会调用子类复写的成员

python">class Father:n = 1def Fun(self):print("父类")class Brother(Father):def Fun(self):print("子类")print()#方式一调父类成员print(Father.n)Father.Fun(self)print()#方法二调用父类成员print(super().n)super().Fun()test = Brother()
test.Fun()

8. 类型注解

Python在3.5版本的时候引入了类型注解,以方便静态类型检查工具,IDE等第三方工具。

类型注解:在代码中涉及数据交互的地方,提供数据类型的注解(显式的说明)。

主要功能
帮助第三方IDE工具(如PyCharm)对代码进行类型推断,协助做代码提示,帮助开发者自身对变量进行类型注释

支持
变量的类型注解
函数(方法)形参列表和返回值的类型注解

8.1 变量类型注解

  1. 语法一: 变量名 : 类型

python">
#变量类型注解
a :int = 1
b :float = 1.0
c :str = "1234"
d :bool = True#类对象类型注解
class Test:passtest :Test = Test()
  1. 语法二: type: 类型

python">#变量类型注解
a  = 1      # type: int
b  = 1.0    # type: float
c = "1234"  # type: str
d  = True   # type: bool#类对象类型注解
class Test:passtest = Test()  # type: Test

一般,无法直接看出变量类型之时会添加变量的类型注解

  1. 类型注解的限制

类型注解主要功能在于:
帮助第三方IDE工具(如PyCharm)对代码进行类型推断,协助做代码提示
帮助开发者自身对变量进行类型注释(备注)

并不会真正的对类型做验证和判断。
也就是,类型注解仅仅是提示性的,不是决定性的

在这里插入图片描述

如上图,是不会报错的哦。

8.2 函数和方法的形参类型注解:

如图所示:
在调用函数(方法),将输入参数的时候,工具没有任何提示(下图)
在这里插入图片描述

在定义函数(方法)的时候,给形参进行注解(下图)
在这里插入图片描述

函数和方法的形参类型注解语法:

python">def 函数(方法)(形参 :类型, 形参 :类型,........) -> 返回值类型 :#...

样例:
在这里插入图片描述

8.3 Union类型

上面的注释是单个的,给大家看一个列表的注释:

python">my_list :list[int] = [1, 2, 3, 4]my_dict :dict[str,int] = {"age" :19, "id" : 1234}

如果我们的 my_list 里面还有其他类型就还需要在相应位置加入相应的类型,这样的话是不是就变得复杂了?有没有解决方法呢?

答:有,Union类型

Union联合类型注解,在变量注解、函数(方法)形参和返回值注解中,均可使用。

使用Union[类型, …, 类型] 可以定义联合类型注解

python">#导包
from typing import Union#                    多个类型                多个类型
my_list :list[ Union[int, float] ]= [1, 2, 3, 4.0, 5.0]#             str 配多个类型          
my_dict :dict[str,Union[int, str]] = {"age" :19, "id" : 1234, "name" : "张三"}

9. 多态

9.1 多态

多态,指的是:多种状态,即完成某个行为时,使用不同的对象会得到不同的状态。

如何理解?

答:比如,老师布置一个任务,同学们用不同的方法解决了这个任务

python">class homework:def English(self):pass#同学接收到作业后开始写
class student_1(homework):def English(self):print("student_1 英语的方法")#同学接收到作业后开始写
class student_2(homework):def English(self):print("student_2 英语的方法")#同样的行为(函数),传入不同的对象,得到不同的状态
#展示出学生的作业
def Fun(student : homework):student.English()#创建对象
stu_1 = student_1()
stu_2 = student_2()#调用函数
Fun(stu_1)
Fun(stu_2)

在这里插入图片描述

9.2 抽象类(接口)

细心的同学可能发现了,父类 homework 的 English 方法,是空实现
在这里插入图片描述

这种设计的含义是:
父类用来确定有哪些方法
具体的方法实现,由子类自行决定

这种写法,就叫做抽象类(也可以称之为接口)

抽象类:含有抽象方法的类称之为抽象类
抽象方法:方法体是空实现的(pass)称之为抽象方法

9.3 抽象类的作用

多用于做顶层设计(设计标准),以便子类做具体实现

对子类的一种软性约束,要求子类必须复写(实现)父类的一些方法
并配合多态使用,获得不同的工作状态

  1. 抽象类就好比定义一个标准,包含了一些抽象的方法,要求子类必须实现。(下列代码)
python">class homework:#语文def Chinses(self):pass#数学def Math(self):pass#英语def English(self):passclass student_1(homework):def Chinese(self):print("student_1 语文的方法")def Math(self):print("student_1 数学的方法")def English(self):print("student_1 英语的方法")class student_2(homework):def Chinese(self):print("student_2 语文的方法")def Math(self):print("student_2 数学的方法")def English(self):print("student_2 英语的方法")
  1. 多态,完成抽象的父类设计(设计标准)和 具体的子类实现(实现标准),下列代码
python">#语文
def Fun_Chinese(student : homework):student.Chinese()#数学
def Fun_Math(student : homework):student.Math()#英语
def Fun_English(student : homework):student.English()#创建对象
stu_1 = student_1()
stu_2 = student_2()#每位同学的语文
Fun_Chinese(stu_1)
Fun_Chinese(stu_2)#每位同学的数学
Fun_Math(stu_1)
Fun_Math(stu_2)#每位同学的英语
Fun_English(stu_1)
Fun_English(stu_2)

http://www.ppmy.cn/embedded/12985.html

相关文章

Qt 实战(1)Qt 概述

一、Qt概述 1、什么是Qt&#xff1f; Qt&#xff08;官方发音 [kju:t]&#xff0c;音同 cute&#xff09;是一个跨平台的 C 开发库&#xff0c;主要用来开发图形用户界面&#xff08;Graphical User Interface&#xff0c;GUI&#xff09;程序&#xff0c;也可以开发不带界面的…

恶补《操作系统》2_1——王道学习笔记

2操作系统-进程 2.1_1 进程的定义、组成、组织方式、特征 组成&#xff1a;PCB&#xff08;进程存在唯一的标志&#xff09;&#xff0c;程序段&#xff0c;数据段 组织方式&#xff1a;链接方式&#xff0c;指针指向不同的队列&#xff1b;索引方式&#xff0c;索引表 特征…

HTML+JS俄罗斯方块小游戏

俄罗斯方块 效果图部分代码领取源码下期内容预报 效果图 部分代码 <!DOCTYPE html> <html><head><meta charset"utf-8" /><title>俄罗斯方块</title><style type"text/css">.MainFrame{border: 1px solid burl…

java+idea+mysql采用医疗AI自然语言处理技术的3D智能导诊导系统源码

javaideamysql采用医疗AI自然语言处理技术的3D智能导诊导系统源码 随着人工智能技术的快速发展&#xff0c;语音识别与自然语言理解技术的成熟应用&#xff0c;基于人工智能的智能导诊导医逐渐出现在患者的生活视角中&#xff0c;智能导诊系统应用到医院就医场景中&#xff0c…

聊聊路径规划算法(二)——图搜索法

图搜索法通过利用已有的环境地图和版图中的障碍物等数据信息建立&#xff0c;由起点至结束点的可行路线。一般分为深度最优和广度最优二种走向。深度优先算法优先拓展搜索深度较大的节点&#xff0c;因此能够更迅速的获得下一个可行路径&#xff0c;不过深度优先算法获取的第一…

第九章 更复杂的光照

Unity的渲染路径 渲染路径决定了光照是如何应用到Unity Shader中的,需要为每个Pass指定它的渲染路径。 完成上面的设置后,我们可以在每个Pass中使用标签来指定该Pass使用的渲染路径。 指定渲染路径是我们和Unity的底层渲染引擎的一次重要的沟通。 前向渲染路径 前向渲染路…

抽象工厂模式设计实验

【实验内容】 楚锋软件公司欲开发一套界面皮肤库&#xff0c;可以对 Java 桌面软件进行界面美化。为了保护版权&#xff0c;该皮肤库源代码不打算公开&#xff0c;而只向用户提供已打包为 jar 文件的 class 字节码文件。用户在使用时可以通过菜单来选择皮肤&#xff0c;不同的…

2024-04-23 linux 查看内存占用情况的命令free -h和cat /proc/meminfo

一、要查看 Linux 系统中的内存占用大小&#xff0c;可以使用 free 命令或者 top 命令。下面是这两个命令的简要说明&#xff1a; 使用 free 命令&#xff1a; free -h这将显示系统当前的内存使用情况&#xff0c;包括总内存、已用内存、空闲内存以及缓冲区和缓存的使用情况。…