3. Python 面向对象编程
文章目录
- Python 面向对象编程
- 1.3.1 面向对象编程理论
- 1.3.1.1 对象
- 1.3.1.2 类
- 1.3.1.3 面向对象编程的特点
- 1.3.2 Python 面向对象编程
- 1.3.2.1 Python 类与对象
- 1.3.2.2 类与对象中的变量
- 1.3.2.3 类与对象中的函数
- 1.3.2.4 \_\_init\_\_ 方法
- 1.3.3 万物皆对象
- 1.3.3.1 重识变量
- 1.3.3.2 重识常量
- 1.3.3.2 重识函数
- 1.3.3.3 重识数据结构
- 1.3.3.4 重识程序
- 1.3.4 练习
- 1.3.4.1 重构成绩管理系统
Python 面向对象编程
在北宋时期,毕昇发明了活字印刷术。他先将文字做成一个个汉字模具,然后按照稿件把单字挑选出来,排列在字盘内,涂墨印刷成书,印完后再将字模拆出,留待下次排印时再次使用。活字印刷术相对于文字书写更加简洁高效,它对印刷业的兴起发挥了重大作用,甚至推动了欧洲文艺复兴的发展。
Python 是一种基于面向对象设计的编程语言,它使用“类”与“对象”进行编程。这里“类”就好比汉字模具,“对象”就好比印刷完的书籍。你不需要一次又一次书写复杂重复的程序,只需要提前编写好需要的类,然后通过类产生具有特定功能的对象即可,这大大提高了 Python 编程的简洁性。
下面我们就通过面向对象的角度重新审视 Python 宇宙,相信你可以感受到面向对象带来的代码简化与效率提升。
1.3.1 面向对象编程理论
在之前的代码中,我们往往采用典型的面向过程编程方式,定义很多函数与变量:
## 定义函数:
函数1
函数2
函数3
函数4## 定义变量:
变量1
变量2
变量3
变量4## 通过变量与函数完成操作
变量3 = 函数1(变量1, 变量2)
变量5 = 函数2(变量3, 变量4)
然而当我们要实现的功能越来越复杂,需要添加的函数与变量也就越来越多。每个函数都有不同的功能,有特定的参数与返回结果,每个变量也有不同的表示意义,程序会变得越来越难以维护。而面向对象通过类与对象的方式解决问题:
## 根据功能定义类1
类1:类函数1
变量:变量1变量2## 根据功能定义类2
类2:类函数2类函数3
变量:变量3变量4变量5## 通过对象完成操作
对象1 = 类1()
对象2 = 类2()
对象2.变量5 = 对象2.函数2(对象1.函数1())
面向对象编程的出现,使得变量和函数可以根据功能进行整理分类,通过面向对象的模块化编程,大大减轻了复杂程序的设计与维护负担。
1.3.1.1 对象
在 Python 中一切都是对象,就像在现实世界中一切都是对象。
在现实中:对象可以是有型的,例如一粒米、一名学生、一辆汽车,甚至一个星球。它也可以是无形的,例如一次演出,一场球赛,一次出差。对象可以简单也可以复杂,复杂的对象可以由许多简单的对象构成,整个世界也可以被认为是一个非常复杂的对象。
在 Python 中:对象可以是有型的,例如一个常量,一个变量,一个序列或字典。它也可以是无形的,例如一个函数。对象可以简单也可以复杂,复杂的对象可以由许多的简单对象组成,整个 Python 程序也可以被当作一个对象。
无论在现实中或 Python 中,对象都具有以下三个特性:
- 每个对象都有一个独特的名字以区别于其他对象。
- 有属性来描述它的某些特征。
- 有一组操作,每个操作决定对象的一种行为。
1.3.1.2 类
类是用来定义对象的 “模板”。
- 在现实中:类是一组具有相同属性和行为的对象的抽象。例如张三、李四虽然每个人有不同的性格与职业,但他们的基本特征是相似的,都有鼻子有眼能吃饭,因此我们统称他们为“人”类,而每一个人就是一个对象。
- 在 Python 中:类是一组具有相同数据和操作的对象的模板集合。例如“学生”类可以由学号、姓名、性别、成绩等表示其属性的数据项和对这些数据的录入、修改和显示等操作组成,而每一个特定的学生例如 XiaoHu 就是一个对象。
1.3.1.3 面向对象编程的特点
面向对象编程有以下几个基本特征:
- 抽象:是将有关事物的特征归纳、集中的过程。通过总结不同“对象”的主要特性设计一个“类”,只强调感兴趣的信息,忽略了与主题无关的信息。
- 封装:是把数据和操作集中在对象内部,并尽可能隐藏对象的内部细节。对象像一个黑匣子,你只要知道它提供的功能,不需要了解其内部的实现方式。
- 继承:是指一个类可以继承另一个类的特征与功能,并添加自己的特征。例如“吉士堡”继承了“汉堡”类,它有面包、菜与肉,但也有独特的一片芝士。
- 多态:指不同的对象进行相同操作时产生多种不同的行为方式。例如“打开”电风扇它会旋转,“打开”电脑屏幕会亮,“打开”抽屉柜子门会开,同样是打开操作,不同对象收到指令后的行为方式是不同的。
1.3.2 Python 面向对象编程
到目前为止,我们接触的变量、运算符、函数等概念来源于 “面向过程” 的编程方式。在上一节中,你可能会对 names.append('Cryin')
这种写法感到疑惑,为什么序列变量 names 可以通过符号 . 调用 append 函数?这种编程方式便是面向对象编程,在这里 names 是一个对象,对象拥有很多类似 append 的函数,每个对象都属于某一个类。
下面我们将介绍 Python 中的面向对象编程方法,并以上一节中的学生成绩管理系统为例方便大家理解。
1.3.2.1 Python 类与对象
Python 使用 class 关键字定义类,类似函数,下面的缩进部分构成了类的主体:
## 创建一个 student 类
class student():pass
使用类的名字和一对括号可以创建类的对象:
## 使用 类的名字 student 与 括号() 可以创建类的对象 xiaohu
xiaohu = student()
xiaoming = student()print(type(xiaohu))
print(type(xiaoming))
<class '__main__.student'>
<class '__main__.student'>
1.3.2.2 类与对象中的变量
我们提到类与对象都有包含一组属性与方法,在 Python 中类的变量用于表示类的属性。student
表示学生类,在我们的系统中我们只关注学生的姓名、数学成绩和语文成绩而不考虑其他,分别用类变量 name
, Math_score
, Chinese_score
表示。这体现了面向对象编程的”抽象性“。
## 创建一个 student 类
class student():## 类的内部定义三个内部变量,并定义他们的初始值name = 'Undefined'Math_score = NoneChinese_score = None
在 Python 中对象拥有与类相同的数据和操作,因此通过类创建的对象也拥有相同的变量。我们使用 .
符号来引用对象或类的变量与函数:
## 使用 类的名字 student 与 括号() 可以创建类的对象 xiaohu
xiaohu = student()
## 使用 . 符号引用对象xiaohu的变量name、Math_score、Chinese_score
print(xiaohu.name)
print(xiaohu.Math_score)
print(xiaohu.Chinese_score)
Undefined
None
None
这里我们通过类创建对象还仅仅是一个初始值,这里我们可以通过赋值符号改变对象内数据的值:
## 通过赋值符号改变对象内变量的值
xiaohu.name = 'XiaoHu'
xiaohu.Math_score = 65
xiaohu.Chinese_score = 55print(xiaohu.name)
print(xiaohu.Math_score)
print(xiaohu.Chinese_score)
XiaoHu
65
55
在这里我们要注意区分两个概念,类变量与对象变量,在上述代码中 student.name
是类变量,xiaohu.name
是对象变量。
- 类变量属于类,更改类变量会影响所有后续由该类创建对象的属性。
- 对象变量属于对象,更改对象变量只影响该对象的属性。
## 更改对象变量只影响该对象的属性。
xiaoming = student()
## 修改 xiaoming.name,xiaohu 的属性不受影响
xiaoming.name = 'XiaoMing'
print(xiaoming.name)
print(xiaohu.name)
XiaoMing
XiaoHu
## 更改类变量会影响所有后续由该类创建对象的属性。
xiaoming = student()
print(xiaoming.name)## 修改 student.name 再次创建新对象 xiaoming
student.name = 'Change Name'
xiaoming = student()## xiaoming.name 不再是 undefined 而是 change name
print(xiaoming.name)
Undefined
Change Name
1.3.2.3 类与对象中的函数
在 Python 中类函数用于表示类的操作,它又被称作为“方法”。它们与之前我们学到的函数类似,但是类函数必须有一个额外的 self 参数:
class student():## 定义类函数时要有一个特殊的 self 参数def print_name(self,):print(self.name)name = 'Undefined'Math_score = NoneChinese_score = None
xiaohu = student()
xiaohu.name = 'Xiaohu'
xiaohu.print_name()
Xiaohu
self 函数用于在类的内部指向对象本身,它是用于连接 类 与 对象 的工具,也是 Python 面向对象编程“多态”特性的一种体现。
例如在上述代码,我们使用 student 类产生对象 xiaohu,那么 self 就代指 xiaohu;如果我们产生对象 xiaoming,那么 self 就会自动代指 xiaoming。因此 self 参数可以根据不同对象产生不同操作,这体现了面向对象编程的“多态性”。
我们还可以给 student 创建一个用于更改成绩的方法,这样我们后续就不需要通过赋值符号更改对象内的数据:
class student():## 定义一个修改对象数据值的函数def change_score(self, course_name, score):if course_name == 'Math':self.Math_score = scoreelif course_name == 'Chinese':self.Chinese_score = score## 如果输入的 course_name 不是 Math 或者 Chinese,则输出错误信息else:print(course_name, " course is still not in current system")def print_name(self,):print(self.name)name = 'Undefined'Math_score = NoneChinese_score = None
xiaohu = student()
xiaohu.name = 'Xiaohu'
xiaohu.change_score('Math', 65)
xiaohu.change_score('Chinese',55)
xiaohu.change_score('Physics',48)
Physics course is still not in current system
随着系统的迭代,系统的复杂度将会直线上升。假设当我们有了十多种课程后,采用 change_score 函数要比直接为一个个课程的成绩赋值更加优雅,用户不再需要了解 student 类中有定义哪些变量等复杂细节,只需要了解 change_score 函数的用法便可以更改学生成绩,这体现了面向对象编程的“封装性”。
1.3.2.4 __init__ 方法
在之前的代码中,我们采用赋值符号来为对象产生初始值:
xiaohu.name = 'XiaoHu'
xiaohu.Math_score = 65
xiaohu.Chinese_score = 55
然而这种方式或许有些麻烦,其实 Python 类中有一种 __init__
方法专门用于初始化对象。这个方法在通过类创建对象时被自动调用,并按照你的想法初始化该对象。下面我们通过 __init__
方法重新定义 student 类:
class student():## 定义 __init__ 方法,通过该方法的参数输入初始值,在该方法内部为变量赋值def __init__(self, name, Math_score, Chinese_score):self.name = nameself.Math_score = Math_scoreself.Chinese_score = Chinese_scoredef change_score(self, course_name, score):if course_name == 'Math':self.Math_score = scoreelif course_name == 'Chinese':self.Chinese_score = score## 如果输入的 course_name 不是 Math 或者 Chinese,则输出错误信息else:print(course_name, " course is still not in current system")def print_name(self,):print(self.name)name = 'Undefined'Math_score = NoneChinese_score = None
在定义了 __init__
方法后,我们通过在类后面的小括号内传递参数的方式初始化对象:
##
xiaohu = student('XiaoHu',65,55)
xiaohu.print_name()
XiaoHu
1.3.3 万物皆对象
对象是 Python 中最核心的概念,犹如道教中 “一生二,二生三,三生万物”,Python 中万物皆源于对象。下面我们在面向对象编程的角度回顾之前学习的变量、函数以及数据结构。
1.3.3.1 重识变量
在 Python 中所有变量都是对象,下面我们创建一个 int 变量,它有 bit_lenth, conjugate, to_byte, from_byte 等方法。我们测试一下 to_byte 方法:
variable = 1
type(variable)
int
to_byte 将 int 对象转化成 byte 对象 b’\x00x\01’ 因为整数 1 的二进制编码是 0001。
variable_byte = variable.to_bytes(2, byteorder = 'big')
print(variable_byte)
print(type(variable_byte))
b'\x00\x01'
<class 'bytes'>
1.3.3.2 重识常量
Python 中的常量也是对象,其中最常用到对象方法的是字符串常量。
字符串常用方法如下:
format()
: 用于从其他信息中构造字符串。replace()
: 用于替代字符串中的某个字符或子串。split()
: 用于通过某种字符分隔字符串。upper()
: 把字符串转换成大写。lower()
: 把字符串转化成小写。
## format 方法使用 {数字 i} 对应 (第i个变量) 来控制用于构造字符串的参数
print("Learn {0} in a {1} way!!".format('Python','smart'))
print("Learn {0} in a {1} way!!".format('PHP','hard'))
Learn Python in a smart way!!
Learn PHP in a hard way!!
## replace 方法使用一个或多个参数分隔字符串,并返回子串构成的序列
print("Learn Python in a smart way!!".replace('smart','hard'))
Learn Python in a hard way!!
## split 方法使用一个或多个参数分隔字符串,并返回子串构成的序列
print("Learn Python in a smart way!!".split(' '))
['Learn', 'Python', 'in', 'a', 'smart', 'way!!']
## upper 和 lower 方法转化大小写
print("Learn Python in a smart way!!".upper())
print("Learn Python in a smart way!!".lower())
LEARN PYTHON IN A SMART WAY!!
learn python in a smart way!!
1.3.3.2 重识函数
更神奇的是,在 Python 中函数也是对象,因此函数也有自己的数据与方法。
def check_sum(num1, num2, target):## 在 def xxx(): 下面缩进的是函数的内容a = num1b = num2return a + b == target
通过 .__name__
成员变量可以获得函数的名字:
check_sum.__name__
'check_sum'
1.3.3.3 重识数据结构
现在你可以想象到,数据结构也理所应当是对象。是的,数据结构为我们提供了许多非常的方法!上一节中的 append
就是其中一个。
l = [1,2,3,4]
l.append(5)
print(l)
[1, 2, 3, 4, 5]
除此之外,我们可以通过 pop
方法替代 del
关键字删除序列内某个元素:
l.pop(1)
print(l)
[1, 3, 4, 5]
通过 insert
方法在特定位置增加元素:
## 第一个参数是位置,第二个参数是插入的元素
l.insert(0,1)
print(l)
[1, 1, 3, 4, 5]
同样的,在元组、字典、集合等数据结构中也提供了很多方法,在此将常用的方法总结如下:
列表
append(x)
把元素 x 放在入列表尾部count(x)
统计元素 x 在列表中出现次数extent(seq)
把新列表 seq 合并到列表尾部index(x)
返回元素 x 在列表第一次出现的位置insert(index, x)
把元素 x 插入到 index 位置pop(index)
删除并返回 index 所在位置的元素remove(x)
删除出现的第一个 x 元素reverse()
颠倒列表顺序sort()
对列表进行排序
字典
clear()
清楚字典内所有元素copy()
返回字典的一个复制has_key(key)
检查 key 是否在字典中items()
返回一个含由 (key, value) 格式元组构成的列表keys()
返回由键构成列表values()
返回由值构成的列表setdefault(key, default)
为键 key 添加默认值 defaultpop(key)
删除 key 并返回对应的值
集合
add(x)
向集合中添加元素 xclear()
清空集合copy()
返回集合的一个复制difference(set)
返回集合与另一个集合的差集discard(x)
删除元素 xisdisjoint(set)
判断两个集合是否有交集issubset(set)
判断新集合 set 是否是集合的子集issuperset()
判断新集合 set 是否是集合的超集
1.3.3.4 重识程序
在某种意义上,我们也可以认为 Python 程序是一个对象,它也有自己的数据和方法。其中 __name__
就是它的一个变量,我们并没有定义过这个变量,但由于它是程序的对象变量,因此可以直接调用。
__name__
'__main__'
1.3.4 练习
1.3.4.1 重构成绩管理系统
此练习是开放题,使用 面向对象 的编程方法重构之前的成绩管理系统,并完成之前的任务。
Task 1. 在上一次期末考试中,XiaoHu 考了数学 65 分,语文 55 分;XiaoMing 考了数学 80 分,语文92 分;XiaoWei 考了数学 95 分,语文 98 分,以此建立学生成绩管理系统。
Task 2. 在本次期末考试中,XiaoHu 考了数学 95 分,语文 85 分;XiaoMing 考了数学 75 分,语文 71 分;XiaoWei 考了数学 92 分,语文 93 分,以此对之前的成绩进行更新。
Task 3. 由于 XiaoMing 的成绩出现了大幅度下滑,家长决定要 XiaoMing 转学到另一所高中,以此在系统中删除 XiaoMing 的信息。
Task 4. 学校新转来的学生 Cryin 本次考试成绩为 数学 87 分,语文 88 分,在系统中录入 Cryin 的成绩。
class student():def __init__(self, name, Math_score, Chinese_score):self.name = nameself.Math_score = Math_scoreself.Chinese_score = Chinese_score## repr 函数用于定义对象被输出时的输出结果def __repr__(self):return str((self.name, self.Math_score, self.Chinese_score))def change_score(self, course_name, score):if course_name == 'Math':self.Math_score = scoreelif course_name == 'Chinese':self.Chinese_score = scoreelse:print(course_name, " course is still not in current system")def print_name(self,):print(self.name)name = 'Undefined'Math_score = NoneChinese_score = None
之前我们实现了学生类,现在我们通过把学生对象保存在字典中实现一个成绩系统。
## Task1
ab = {}
ab.setdefault('XiaoHu', student('XiaoHu', 65, 55))
ab.setdefault('XiaoMing', student('XiaoMing', 80, 92))
ab.setdefault('XiaoWei', student('XiaoHu', 95, 98))
print(ab)## Task2
ab['XiaoHu'].change_score('Math', 95)
ab['XiaoMing'].change_score('Math', 75)
ab['XiaoWei'].change_score('Math', 92)ab['XiaoHu'].change_score('Chinese', 85)
ab['XiaoMing'].change_score('Chinese', 71)
ab['XiaoWei'].change_score('Chinese', 93)
print(ab)## Task3
ab.pop('XiaoMing')
print(ab)## Task4
ab.setdefault('Cryin', student('Cryin', 87, 88))
print(ab)
{'XiaoHu': ('XiaoHu', 65, 55), 'XiaoMing': ('XiaoMing', 80, 92), 'XiaoWei': ('XiaoHu', 95, 98)}
{'XiaoHu': ('XiaoHu', 95, 85), 'XiaoMing': ('XiaoMing', 75, 71), 'XiaoWei': ('XiaoHu', 92, 93)}
{'XiaoHu': ('XiaoHu', 95, 85), 'XiaoWei': ('XiaoHu', 92, 93)}
{'XiaoHu': ('XiaoHu', 95, 85), 'XiaoWei': ('XiaoHu', 92, 93), 'Cryin': ('Cryin', 87, 88)}
3. Python 面向对象编程相关推荐
- 这可能是Python面向对象编程的最佳实践
作者 | 崔庆才 来源 | 进击的Coder(ID:FightingCoder) Python 是支持面向对象的,很多情况下使用面向对象编程会使得代码更加容易扩展,并且可维护性更高,但是如果你写的多了 ...
- Python面向对象编程:类继承和其衍生术语
Python面向对象编程03:类继承和其衍生术语 前面我们讲到过正则表达式字符等,上一篇分享了面向对象编程和类的结构,最后稍微提到了继承. Python面向对象编程:深度认识类class_ Pytho ...
- 《Python面向对象编程指南》——1.2 基类中的__init__()方法
本节书摘来自异步社区<Python面向对象编程指南>一书中的第1章,第1.2节,作者[美]Steven F. Lott, 张心韬 兰亮 译,更多章节内容可以访问云栖社区"异步社区 ...
- 关于python面向对象编程中、下列说法中_关于Python面向对象编程的知识点总结
前言 如果你以前没有接触过面向对象的编程语言,那你可能需要先了解一些面向对象语言的一些基本特征,在头脑里头形成一个基本的面向对象的概念,这样有助于你更容易的学习Python的面向对象编程. 接下来我们 ...
- python对象编程例子-这是我见过最详细的Python面向对象编程!建议收藏!
原标题:这是我见过最详细的Python面向对象编程!建议收藏! 面向对象编程和函数式编程(面向过程编程)都是程序设计的方法,不过稍有区别. 面向过程编程: 1. 导入各种外部库 2. 设计各种全局变量 ...
- python面向对象编程的优点-Python面向对象编程——总结面向对象的优点
Python面向对象编程--总结面向对象的优点 一.从代码级别看面向对象 1.在没有学习类这个概念时,数据与功能是分离的 def exc1(host,port,db,charset): conn=co ...
- python编程基础是什么-Python面向对象编程基础解析(一)
1.什么是面向对象 面向对象(oop)是一种抽象的方法来理解这个世界,世间万物都可以抽象成一个对象,一切事物都是由对象构成的.应用在编程中,是一种开发程序的方法,它将对象作为程序的基本单元. 2.面向 ...
- 【Python基础】Python 面向对象编程(上篇)
我的施工计划图 已完成专题包括: 1我的施工计划 2数字专题 3字符串专题 4列表专题 5流程控制专题 6编程风格专题 7函数使用专题 今天是面向对象编程的上篇:基础专题 Python 面向对象编程 ...
- Python 面向对象编程基础
Python面向对象编程 简介:面向对象编程--Object Oriented Programming,简称 OOP,是一种程序设计思想.OOP 把对象作为程序的基本单元,一个对象包含了数据和操作数据 ...
- python面向对象编程138讲_Python面向对象编程简单讲解
学习目标: 1-面向对象编程 2-类和对象 3-对象的属性和方法 4-类的特性 Python面向对象编程 一种编程程序的设计思想,把对象作为程序的基本单元,一个对象包含了数据和操作数据的函数.把计算机 ...
最新文章
- 我的Objective-C系列文章
- Android利用Volley异步加载(JSON和图片)完整示例
- tracker服务器列表2020_个人服务器采购整理分享
- 多元线性回归数据集_TensorFlow学习Program1——13.实现一元、多元线性回归(基于房价数据集)...
- Lenovo System x3650 M5 使用ServerGuide安装win2016(U盘安装)
- 你的计算机没有安装cad2006,CAD2006安装常见问题及处理方法
- 史上最新最全的ADB命令行
- 美通企业日报 | 英特尔与阿里云签署战略合作备忘录;赛默飞在苏州扩建临床试验工厂...
- 2021年京东最新炸年兽活动用脚本会怎样?JD炸年兽活动参与教程
- 大数据毕设选题 - 机器学习餐厅销量预测(大数据 python)
- 【neon加速拆分/合并交叉数据】使用neon intrinsics加速合并/拆分uv的内存分布(交叉存储/分别存储)
- 建模:蒙特卡洛法求多重积分
- 虚拟化及vmware产品介绍
- Java能自学吗?如何自学?(附Java学习路线图)
- 速卖通买家号怎么注册?
- 朋友没有邀请码,也成功让我使用了Club House
- w10 恢复 已清空回收站的文件
- 赵聪慧 java,基于Instrumentation的JAVA代码暖替换
- AXI 总线协议学习笔记(3)
- PL/SQL 11g R2 —— 包
热门文章
- html5 mac os 开发工具,如何通过TextMate或命令行在Mac OS上使用W3C tidy-html5软件包?...
- 计算机专业试讲10分钟教案,10分钟试讲教案怎么写
- PAJ7620手势传感器快速应用- -基于涂鸦CBU模组开发板
- 【浏览器工作原理与实践笔记一】:宏观视角上的浏览器
- Android studio获取服务器端json数据并解析
- MathType中输入矩阵转置符号(向下丁字符号 Down tack,形状类似大写字母T)
- python编译 pyd 工具_avalon-fsn首页、文档和下载 - Python 编译构造工具 - OSCHINA - 中文开源技术交流社区...
- 网上下载的avi格式视频,没有画面怎么办?
- Java输入输出数据流
- 堡垒机jumpserver 搭建与使用