Python-九、面向对象
1、两种编程思维
以炒番茄鸡蛋为例:
【面向过程】:编程主要用到的是“函数”知识,将每个过程步骤打包成函数,再依次调用。
简单的讲,面向过程主要用到的是“函数”知识。
【面向对象】:我们直接面对的是机器人,而非炒菜的过程,所以这里机器人就是我们面对的对象。
简单的讲,面向对象主要用到的是“类与对象”知识。【类】是【对象】的母板,得先有了类,我们才能制造各种“对象”。就像我们先有了产品图纸,才能制造各种产品一样。
2、类是一个函数包
理解【类】最简单的方式:【类】是一个函数包。类中可以放置函数和变量,然后类中的函数可以很方便的使用类中的变量。
image.png
2.1、类中可以放置函数和变量
class 智能机器人():
胸围 = 33
腰围 = 44
臀围 = 55
def 打招呼():
print('主人你好!')
def 卖萌():
print('主人,求抱抱!')
def 生气():
print('主人,我要报警了!')
def 奔跑():
print('我快乐地奔跑、奔跑……哎呦喂!撞墙了。')
智能机器人.奔跑()
在上述的智能机器人
类中,我们放置了机器人的腰围
等变量,以及打招呼
等函数。类方法也是函数,那和我们之前学的单独定义函数有什么区别吗?
它们两区别,一个是它的调用格式:类.函数名()
比函数名()
多了一个【类.】,但更重要的是,“类”中的函数可以利用“类”中的变量(也就是类方法可以调用类属性)。
2.2、类方法和类属性可以组合
class 类A():
变量1 = 100
变量2 = 200
@classmethod #① 第一个格式
def 函数1(cls): #② 第二个格式
print(cls.变量1) #③ 第三个格式
print(cls.变量2)
类A.函数1()
*函数1()的功能是:把类中的变量1和变量2打印出来。
在这里,为了把类中的变量传递给类中的函数,我们需要用到3个特定格式:
① 第一个格式@classmethod
的中文意思就是“类方法”,@classmethod
声明了函数1
是类方法,这样才能允许函数1
使用类属性中的数据。
② 第二个格式cls
的意思是class
的缩写。如果类方法函数1
想使用类属性(也就是类中的变量),就要写上cls
为函数1
的第一个参数,也就是把这个类作为参数传给自己,这样就能被允许使用类中的数据。
③ 第三个格式是cls.变量
。类方法想使用类属性的时候,需要在这些变量名称前加上cls.
。
比类方法
和类
之间的约法三章,所以但凡有任何格式错误都会报错。
让机器人自报三围
class 智能机器人():
胸围 = 33
腰围 = 44
臀围 = 55
def 打招呼():
print('主人你好!')
def 卖萌():
print('主人,求抱抱!')
def 生气():
print('主人,我要报警了!')
@classmethod
def 自报三围(cls):
print('主人,我的三围是:')
print('胸围:%s' % (cls.胸围))
print('腰围:%s' % (cls.腰围))
print('臀围:%s' % (cls.臀围))
print('哈哈哈哈哈,下面粗上面细,我长得像个圆锥。')
智能机器人.自报三围()
这个练习中,类方法“自报三围”通过cls的格式,取得了类属性“胸围、腰围、臀围”的值并打印了出来。这个过程中,数据是按箭头方向流转的:
智能机器人.自报三围在实际编程中,通过【数据流转】,我们还能让类为我们做更多事情。
3、给类方法传参
既然函数能传递参数,类方法能不能传递参数呢?答案是肯定的。我们谈一谈如何给类方法传参。
3.1、类方法仅使用外部参数
我们可以给函数传递参数被函数内部使用,就像这样:
class add_100():
def add_100(num):
sum = num + 100
print('计算结果如下:')
print(sum)
num = 1
add_100(num)
num作为外部参数,就被传进去了。
3.2、类方法仅使用内部参数
前例智能机器人代码中的@classmethod就是内部参数的使用方法。
3.3、类方法同时使用内部参数和外部参数
class add_100():
sum = 100
@classmethod
def add_100(cls,num):
cls.sum = num + cls.sum
print('计算结果如下:')
print(cls.sum)
num = int(input('请输入一个整数:'))
add_100.add_100(num)
在上例中,我们就同时调用了外部用户输入的的num
和内部的sum
(cls)两个函数。
假如我们想要使用多个参数,则要添加对应的函数哦:
def add_100(cls,num1,num2,num3):
4、增加/修改类属性
有两种途径来增加或修改类属性。一种是从内部,用类方法去增加/修改;另一种是从外部,用类.变量 = xx直接增加/修改类属性。
增加/修改类属性4.1、从外部增加/修改属性
class 类A(): #空类
pass
类A.变量1 = 100 #调用类A(空类)并增加了一个值为100的变量1
print(类A.变量1) #打印类A的变量1,结果是100
类A()是一个空类(里面的pass语句代表“什么都不做”),利用类A.变量1,我们在外部给类A()添加了一个类属性变量1,然后使用print语句把类属性打印了出来。
从外部给空类A赋值4.2、从内部增加/修改属性
class 念诗类():
一首诗 = ['《卜算子》','我住长江头,','君住长江尾。','日日思君不见君,','共饮长江水。']
@classmethod
def 念诗函数(cls):
cls.接收人 = input('请输入你想给谁念诗:') #在类的内部增加"接收人"
print('念给%s的诗:'%(cls.接收人))
for i in cls.一首诗:
print(i)
念诗类.念诗函数()
从内部增加/修改属性
5、练习
练习目标:
我们会通过今天的作业,再次实践类属性和类方法的创建和调用。
练习要求:
小明是一家公司的hr,公司这一年发展很好,打算给员工们发福利。
所以,要给员工评绩效。你能用今天学到的知识帮小明实现这个功能吗?
对了,小明的 boss 很抓细节,所以在录入员工名字时必须录对,不能错。
STEP、1:
首先,我们得把信息录入和打印的模块搞出来,完成基础的信息录入。
STEP、2:
我们得知道评绩效的类方法是什么?于是我们咨询了HR,告知:
绩效评定的具体规则:
kpi > 95 评为明星员工
80 <= kpi <= 95 评为优秀员工
kpi < 80 一般员工,没有奖杯
STEP、3:
我们得判断该员工却属于该公司雇员,否则就录入失败。
# 创建一个人事系统类
class hrSystem:
# 创建存储员工名字的变量 name
name = ''
# 创建存储员工工资的变量 salary
salary = 0
# 创建存储员工绩效的变量 kpi
kpi = 0
# 定义录入员工信息的类方法
@classmethod
def record(cls, name, salary, kpi):
cls.name = name
cls.salary = salary
cls.kpi = kpi
# 定义打印员工信息的类方法
@classmethod
def print_record(cls):
if cls.check_name(): # 以 cls.check_name() 的返回值(0或1)作为判断条件。
print(cls.name + '的工作信息如下:')
print('本月工资:' + str(cls.salary))
print('本年绩效:' + str(cls.kpi))
# 定义根据 kpi 评奖的类方法
@classmethod
def kpi_reward(cls):
if cls.kpi > 95:
print('恭喜' + cls.name + '拿到明星员工奖杯!')
elif cls.kpi <= 95 and cls.kpi >= 80:
print('恭喜' + cls.name + '拿到优秀员工奖杯!')
else:
print('很遗憾' + cls.name + '这次没有评上奖杯,希望来年努力工作,勇创佳绩!')
# 检查录入名称是否正确的类方法
@classmethod
def check_name(cls):
if cls.name not in ['bob', 'candy', 'jony', 'kelly']:
print('录入错误!' + cls.name + '不是本公司员工!')
return 0 # 设置返回值为0
else:
print('录入正确~')
return 1 # 设置返回值为1
# 验证结果的代码
hrSystem.record('spy', 3000, 60)
hrSystem.print_record()
hrSystem.record('bob', 3000, 60)
hrSystem.print_record()
6、习题-简单的日程安排
练习目标
通过这个练习,你可以通过类方法实现简单的日程安排。
练习要求
为类calendar添加两个方法:一个删除完成项,一个添加新增项。
由于日程安排是事情和时间的配对,所以我们用字典来存放:
{'给父母买礼物':'9:00', '学习':'10:00', '和朋友聚会':'18:30'}
接下来,需要你新建两个类方法,从而实现字典中的数据增减。
'''
为类calendar添加两个方法:一个删除完成项,一个添加新增项。
由于日程安排是事情和时间的配对,所以我们用字典来存放:
{'给父母买礼物':'9:00', '学习':'10:00', '和朋友聚会':'18:30'}
接下来,需要你新建两个类方法,从而实现字典中的数据增减。
'''
class calendar:
# 日程表的日期
date = '2020-08-08'
# 待办清单,以字典形式给出,键为事件,值是安排的时间
todo_list = {'给父母买礼物':'9:00', '学习':'10:00', '和朋友聚会':'18:30'}
# 添加具体的待办事件为键,时间安排为值
todo = ''
time = ''
# 添加待办完成后,删除待办的类
@classmethod
def todo_done(cls,todo):
# 将外部传入值存储在类中
cls.todo = todo
# 在待办清单中查找传入值,如果找到就删掉。
for i in list(cls.todo_list):
if cls.todo == i:
del cls.todo_list[i]
print(cls.todo_list)
# 添加新增待办的类
@classmethod
def add_todo(cls,todo,time):
cls.todo_list[todo] = time
print(cls.todo_list)
calendar.todo_done('给父母买礼物')
calendar.add_todo('写日记', '20:00')
代码简化后
class calendar:
# 日程表的日期
date = '2020-08-08'
# 待办清单,以字典形式给出,键为事件,值是安排的时间
todo_list = {'给父母买礼物':'9:00', '学习':'10:00', '和朋友聚会':'18:30'}
# 添加待办完成后,删除待办的类
@classmethod
def todo_done(cls,todo):
# 将外部传入值存储在类中
del cls.todo_list[todo]
# 添加新增待办的类
@classmethod
def add_todo(cls,todo,time):
cls.todo_list[todo] = time
calendar.todo_done('给父母买礼物')
calendar.add_todo('写日记', '20:00')
print(calendar.todo_list)