类与对象(三)
前言
与面向对象编程相对应的是面向过程编程。
面向过程编程
面向过程编程:首先分析出解决问题所需要的步骤(即“第一步做什么,第二步做什么,第三步做什么”),然后用函数实现各个步骤,再依次调用。
示例代码:
import math # 变量key代表循环运行程序的开关 key = 1 # 采集信息的函数 def myinput(): choice = input('请选择计算类型:(1-工时计算,2-人力计算)') if choice == '1': size = float(input('请输入项目大小:(1代表标准大小,请输入小数)')) number = int(input('请输入人力数量:(请输入整数)')) time = None return size,number,time # 这里返回的数据是一个元组 if choice == '2': size = float(input('请输入项目大小:(1代表标准大小,请输入小数)')) number = None time = float(input('请输入工时数量:(请输入小数)')) return size,number,time # 这里返回的是一个元组 # 完成计算的函数 def estimated(my_input): # 把元组中的数据取出来 size = my_input[0] number = my_input[1] time = my_input[2] # 人力计算 if (number == None) and (time != None): number = math.ceil(size * 80 / time) print('项目大小为%.1f个标准项目,如果需要在%.1f个工时完成,则需要人力数量为:%d人' %(size,time,number)) # 工时计算 elif (number != None) and (time == None): time = size * 80 / number print('项目大小为%.1f个标准项目,使用%d个人力完成,则需要工时数量为:%.1f个' %(size,number,time)) # 询问是否继续的函数 def again(): # 声明全局变量key,以便修改该变量 global key a = input('是否继续计算?继续请输入y,输入其他键将结束程序。') if a != 'y': # 如果用户不输入'y',则把key赋值为0 key = 0 # 主函数 def main(): print('欢迎使用工作量计算小程序!') while key == 1: my_input = myinput() estimated(my_input) again() print('感谢使用工作量计算小程序!') main()
编码思路
我们根据“采集信息——计算数据——继续采集信息”这个过程封装了三个函数,再依次调用,按规定顺序执行程序。
面向对象编程
而面向对象编程,会将程序看作是一组对象的集合(还记得对象包括类对象和实例对象吧)。
用这种思维设计代码时,考虑的不是程序具体的执行过程(即先做什么后做什么),而是考虑先创建某个类,在类中设定好属性和方法,即是什么,和能做什么。
接着,再以类为模版创建一个实例对象,用这个实例去调用类中定义好的属性和方法即可。
如果把上述面向过程编程的代码改成面向对象编程,我们可以先创建一个Project类,在类中定义好属性和方法,再创建一个实例。
示例代码
代码就是这样的,大致感受一下即可:
import math class Project: def __init__(self): self.key = 1 def input(self): choice = input('请选择计算类型:(1-工时计算,2-人力计算)') if choice == '1': self.size = float(input('请输入项目大小:(1代表标准大小,请输入小数)')) self.number = int(input('请输入人力数量:(请输入整数)')) self.time = None if choice == '2': self.size = float(input('请输入项目大小:(1代表标准大小,请输入小数)')) self.number = None self.time = float(input('请输入工时数量:(请输入小数)')) def estimated(self): # 人力计算 if (self.number == None) and (self.time != None): self.number = math.ceil(self.size * 80 / self.time) print('项目大小为%.1f个标准项目,如果需要在%.1f个工时完成,则需要人力数量为:%d人' %(self.size,self.time,self.number)) # 工时计算 elif (self.number != None) and (self.time == None): self.time = self.size * 80 / self.number print('项目大小为%.1f个标准项目,使用%d个人力完成,则需要工时数量为:%.1f个' %(self.size,self.number,self.time)) def again(self): a = input('是否继续计算?继续请输入y,输入其他键将结束程序。') if a != 'y': # 如果用户不输入'y',则把key赋值为0 self.key = 0 # 主函数 def main(self): print('欢迎使用工作量计算小程序!') while self.key == 1: self.input() self.estimated() self.again() print('感谢使用工作量计算小程序!') # 创建实例 project1 = Project() project1.main()
编码思路
可以发现,在此例中,用类编写一个直观的好处就是参数的传递会比普通函数要省事很多,也不必考虑全局变量和局部变量,因为类中的方法可以直接调用属性。
可想而知,当项目难度越大,需要的参数越多,用类编写在程序的可拓展性、可读性、维护成本都会更胜一筹。
这就是面向对象编程:以对象为中心,将计算机程序看作一组对象的集合。
面向对象VS面向过程
对比图如下:
总结一下:和之前说过的函数类似,面向对象编程实际上也是一种对代码的封装。只不过,类能封装更多的东西,既能包含操作数据的方法,又能包含数据本身。所以,代码的可复用性也更高。
而且,对于需要长期更新的代码而言,面向对象编程写成的代码结构会更清晰。所以,代码的可读性、可拓展性和可维护性这几个方面都会优于面向过程编程。
还有一点不得不提的是:面向对象编程,将代码具体的数据和处理方法都封装在类中,让我们不用完全了解过程也可以调用类中的各种方法。
这个优势让我们可以在 Python 中轻松地调用各种标准库、第三方库和自定义模块(可以简单理解成别人写好的类),这是Python 之所以这么强大和热门的主要原因之一。
这也是为什么我在开头说“面向对象编程,会为你打开一个新的世界”。将他人封装好的代码为自己所用,效率和能做的事情自然是天壤之别。
不过万丈高楼平地起,这些我们以后能够做到的事,都是建立在今天的基础学习和练习之上。
结语
好,现在请你将目光从屏幕上稍稍移开一会儿,在大脑里回顾一下自己对类、实例、对象、属性和方法这些词的理解。
已经都过了一遍了吗?确定的话,再往下走。
你是否想到现实中的类(如鸟类)和编程中的类(如 int)的对比?是否想到了某群体下的某个体,类似于某个类创建的某个实例?
是否想到了现实事物也存在着属性(具有一定特征)和方法(能完成某些行为)?是否……
所以,可以说:编程世界的创建,是基于人对现实世界的理解。只要你用心留意,就能发现这两个世界之间各种关联,包括之前学过的知识。
编程能将对世界的理解投射到代码里,反过来,编程也能通过代码来影响世界。从这个角度来看,改变世界这件事离我们其实都并不远。
希望编程可以加深你对世界的理解,并增强你改变世界的能力。
关于类,今天只提到了基础概念和基础用法。除了类的创建和调用外,还有一些类的操作,是类成为面向对象编程中的主要工具的真正原因。
那么类的高阶操作主要有哪些呢?下一站我们继续探讨!