signed

QiShunwang

“诚信为本、客户至上”

编程实例对比

2021/6/3 13:08:08   来源:

面对过程编程与面对对象编程对比

  • 一、面对过程编程举例
    • 1.整理需求,明确目的
      • 1)功能介绍
      • 2)已知信息
      • 3)功能演示
    • 2.分析流程,拆解项目
      • 1)配送次数计算
      • 2)快递员数量计算
      • 3)公式的细节处理
  • 二、面对对象编程举例
    • 1、整理需求,明确目的
    • 2、分析流程,拆解项目
      • 1)菜单类的框架建设
      • 2)菜单类缺失的执行方法设计
      • 3)各按键功能实现的代码合并
  • 三、面对过程编程与面对对象编程对比

一、面对过程编程举例

下面以设计计算快递配送调配程序为例,实践面对过程编程

1.整理需求,明确目的

1)功能介绍

已知快递总量、快递员数量,计算配送次数,或根据快递总量,配送次数计算需要的快递员数

2)已知信息

标准大小的集装箱内有100件快递,每个快递员一次可以配送20件快递。

3)功能演示

2倍标准大小集装箱有200件快递,当快递员数量为2人时,系统计算出需要五次可以完成配送
0.6倍标准大小集装箱有60个快递,想要一次性完成配送需要安排三个快递员

2.分析流程,拆解项目

不能着急于编程开发,先梳理清楚项目的任务需求,做出程序功的运行效果预期:

1)配送次数计算

输入:集装箱大小(浮点数,代表标准大小的倍数)、快递员数(整数)
输出:配送次数
代码实现:

size = float(input('请输入集装箱大小:')) #例:输入2
person = int(input('请输入快递人员数量:')) #例:输入2
num = int(size*100/20/person) #配送次数计算公式
print('%s个标准集装箱大的快递项目,使用%d快递员配送,\
则需要配送次数:%d'%(size,person,num))
#输出结果为:
#请输入集装箱大小:2
#请输入快递人员数量:2
#2个标准集装箱大的快递项目,使用2快递员配送,则需要配送次数: 5

2)快递员数量计算

输入:集装箱大小(浮点数,代表标准大小的倍数)、需要的配送次数(整数)
输出:分配快递员数(整数)
代码实现

size = float(input('请输入集装箱大小:'))#例:输入0.6
num = int(input('请输入想要配送几次:'))#例:输入1
person = int(size/num*100/20) #快递员数量计算公式
print('%s个标准集装箱大的快递项目,%d次配送完毕,\
则需要配送员数:%d'%(size,num,person))
#输出结果为:
# 请输入集装箱大小:0.6
# 请输入想要配送几次:1
# 0.6个标准集装箱大的快递项目,1次配送完毕,则需要配送员数: 3

3)公式的细节处理

两个公式已经写好,但此处出现一个问题,现实生活中,无论是配送次数还是需要调配的快递员数量,都需要取一个大于或等于计算结果的整数,因此,我们需要一个函数对算得的结果进行向上取整:
ceil函数

import math

math.ceil()

使用这个函数时,需要引用math。
实际测试中又发现了另一个问题,当需要通过上述公式计算2.2个标准集装箱,1个配送员,需要配送多少次时:

import math
print(2.2*100/20)
print(math.ceil(2.2*100/20))
#输出结果为:11.000000000000002
#          12

这里的结果应该是可以整除,输出为11,但由于二进制的除法机制,会导致结果会出现小数。此时,我们需要引用另一个函数进行修正:round()函数

round(x,n)

这个函数可以对小数x进行保留n位小数操作,搭配起来就可以输出我们需要的结果。完善后的公式代码为:

import math
person = int(math.ceil(round((size/num*100/20),2)))

在两个核心功能已经完成,我们将其放入函数

import math
#计算需要配送次数
def calcu_num(size,people):
    num = int(math.ceil(round((size*100/20/person),2)))
    print('%s个标准集装箱大的快递项目,使用%d快递员配送,\
    则需要配送次数:%d' % (size, person, num))
#计算需要的快递员数
def calcu_people(size,num):
    person = int(math.ceil(round((size/num*100/20),2)))
    print('%s个标准集装箱大的快递项目,%d次配送完毕,\
    则需要配送员数:%d' % (size, num, person))

将函数设置好后,为了增加交互性,我们设置一个选择函数:

def select():
    type = int(input('请选择需要计算的工作:1-配送次数\
    计算,2-快递员数计算,请选择:'))
    if type==1:
        执行配送次数计算
    elif type==2:
        执行配送员数量计算
    elif type!=1 and type!=2:
        print('请输入正确数字!')
        return select()

这样,一个选择函数就完成了。但依然有一个问题,如果键入值并非数字,选择函数就无法正常运行了。想要解决这个问题,需要了解python中的异常捕获:try——except语句
我们对这个语句进行一下解析:

while True:
        try:#尝试运行以下代码,运行正确则退出循环
            age = int(input('你今年多大了?'))
            break
        except ValueError:
        #运行到try语句后面,如果产生发生错误类型
        #为"ValueError"的错误,则执行以下操作:
            print('你输入的不是数字!')
#输出结果为:你今年多大了?a
#          你输入的不是数字!
#          你今年多大了?23

在函数中添加这个语句,代码的容错性就有了很大的提升。

以下,我们完成了整个代码。完整版代码如下:

import math
# 选择计算工作的种类
def select():
    try:
        type = int(input('请选择需要计算的工作:1-配送次数\
计算,2-快递员数计算,请选择:'))
        if type == 1:
            return 1

        elif type == 2:
            return 2

        elif type != 1 and type != 2:
            print('请输入正确数字!')
            return select()
    except ValueError:
        print('你输入的不是数字!请重新输入')
        return select()

# 键入计算工作的必要参数
def BOSS_input(type):
    while True:
        try:
            # 输入集装箱大小
            sizes = float(input('请输入项目大小:1代表标准,\
还可以输入其他倍数或小数:'))
            break
        except ValueError:
            print('你输入的不是数字!请重新输入')
    # 根据选择函数返回值确定需要求出哪个结果
    if type == 1:
        while True:
            try:
                # 需要计算运送次数
                others = int(input('请输入投入的快递员数,请输入整数:'))
                break
            except ValueError:
                print('你输入的不是数字!请重新输入')
    else:
        while True:
            try:
                # 需要计算快递员数
                others = int(input('请输入快递次数,请输入整数:'))
                break
            except ValueError:
                print('你输入的不是数字!请重新输入')
    return sizes, others  # 返回一个数组,存储计算工作量所需的参数

# 计算工作量
def calculate_job(data_input,type):
    # 获取参数数值
    sizes = data_input[0]
    others = data_input[1]

    print('计算结果如下')
    if type == 1:
        # 配送次数计算过程
        num = math.ceil(round((sizes * 100 / 20 / others), 2))
        print('%.1f个标准集装箱大的快递项目,使用%d位快递员\
配送,则需要配送次数%d次' % (sizes, others, num))
    elif type == 2:
        # 快递员数计算过程
        person = math.ceil(round((sizes * 100 / 20 / others), 2))
        print('%.1f个标准集装箱大的快递项目,%d次配送完毕,\
则需要快递员数:%d位' % (sizes, others, person))


# 按顺序调用函数进行运算
def res():
    i=select()
    data_input=BOSS_input(i)
    calculate_job(data_input,i)
# 主函数
while True:
    res()
    try:
        jud = int(input('是否继续运行?1—继续 其他任意键—退出:'))
        if jud==1:
            pass

    except ValueError:
        break

这样,我们就完成了可以实现以上功能的代码。感兴趣的小伙伴可以运行起来查看一下结果。

二、面对对象编程举例

下面以模拟共享单车租借平台为例,进行面对对象编程举例

1、整理需求,明确目的

输入数字1:查询车辆,查询平台上所有的车辆信息与租借状态
输入数字2:共享车辆,将车辆添加到系统中,需要输入单车的基本信息
输入数字3:租借车辆,可以租借现有的车辆,租借出去后显示该车辆状态为“已借出”
输入数字4:归还车辆,还车成功后,显示该车辆状态为“带租借”,可再次租借

2、分析流程,拆解项目

我们利用面对对象编程的方式完成该项目,首先需要明确的是需要有多少个类,各个类有多少属性,方法。调用类的属性本质是函数,因此对方法的完善和面对过程编程中对功能函数的完善方法类似。我们需要先编写出整体框架然后逐渐完善类的方法和调用步骤。

1)菜单类的框架建设

首先,我们需要设计一个系统菜单。这个过程需要一个类。系统菜单需要为我们提供按键提示,并进行功能跳转:

class Manage:
    # 菜单函数显示按键提示,并进行对应跳转
    def menu(self):
        print("欢迎使用共享单车租借系统\n")
        while True:
            print('1.查询所有车辆\n 2.共享车辆\n 3.租借车辆\n 4.归还车辆\n 其他任意键.退出系统\n')
            try:
                select = int(input('请输入所需功能对应按键'))
                # 按1跳转车辆信息并输出
                if select == 1:
                    # 输出单车信息
                    
                    # 需要调用对应方法,暂时未设置,下同
                    pass
                #按2跳转向系统内输入单车信息
                elif select == 2:
                    # 进行共享单车操作
                    pass
                    
                #按3跳转租借车辆
                elif select == 3:
                    # 进行租借操作
                    pass
                # 按4跳转归还车辆
                elif select == 4:
                    # 进行归还操作
                    pass
                # 按其他任意键退出系统
                else :
                    print('期待您下次使用!祝您生活愉快!')
                    break
            except ValueError:
                print('期待您下次使用!祝您生活愉快!')
                break

到了这里,我们的菜单函数框架已经完成了,接下来我们需要填充菜单类的方法里缺失的部分:

2)菜单类缺失的执行方法设计

按键1对应方法
输入1后,计算机会进行输出车辆信息的操作,我们设计的车辆信息包括车辆编号、车辆使用年限和车辆租借状态。因为需要输出车辆信息,因此我们需要让系系统录入初始的车辆信息。定义一个Bike类,设置一个可以录入共享车辆的原始信息的方法。由于我们的按键2也需要录入新的车辆信息,因此按键1和2的运行可以产生一定重叠,区别只是有系统输入还是手动输入。因此具体的操作方法为:通过为Bike类设置初始化方法,将车辆的基本信息赋值,作为Bike类的属性:

class Bike:
    #初始化方法 NO代表车辆编号、age代表车辆年限、
    #state代表车辆状态,0代表待租借,1代表租借中
    def __init__(self,NO,age,state=0):
  # state只有在按键输入3,即进行租借操作室时才需要进行人为更改
      # 定义属性NO,age和state,存放自行车的基本信息
        self.NO = NO
        self.age = age
        self.state = state

之后我们就可以调用Bike类赋值一个自行车的基本信息。但需要注意的是,我们不止需要赋值一个车辆的基本信息,因此必须在调用Bike输入车辆信息后,将信息再存储起来,因此,我们为Manage类添加另一个方法:

class Manage:
	bike_list = []

    def __init__(self):
      # 这里录入三个初始车辆的信息,用于模拟系统中原有车辆的信息的录入
        bikeA = Bike(1001,2)
        bikeB = Bike(1002,2)
        bikeC = Bike(1003,1)
      # 将录入的初始车辆信息的地址信息存到列表bike_list中
      # 这个列表内元素的数量同时代表了系统以录入的车辆数
        self.bike_list.append(bikeA)
        self.bike_list.append(bikeB)
        self.bike_list.append(bikeC)

储存好原始车辆信息之后,还需要打印出这些车辆的基本信息,于是我们对bike类进行一点修饰,再将两个部分合并进行测试:

class Bike:
    def __init__(self, NO, age, state=0):
        self.NO = NO
        self.age = age
        self.state = state
        if self.state == 0:
            status = '待租借'
        else:
            status = '租借中'
        return '车辆编号%d 已经运行%d年,车辆状态:%s' % (self.NO, self.age, status)


class Manage:
    bike_list = []

    def menu(self):
        print("欢迎使用共享单车租借系统\n")
        while True:
            print('1.查询所有车辆\n 2.共享车辆\n 3.租借车辆\n 4.归还车辆\n 其他任意键.退出系统\n')
            try:
                select = int(input('请输入所需功能对应按键'))
                # 按1跳转车辆信息并输出
                if select == 1:
                    self.info_bike()
                else:
                    print('期待您下次使用!祝您生活愉快!')
                    break
            except ValueError:
                print('期待您下次使用!祝您生活愉快!')
                break

    def __init__(self):
        bikeA = Bike(1001, 2)
        bikeB = Bike(1002, 2)
        bikeC = Bike(1003, 1)
        self.bike_list.append(bikeA)
        self.bike_list.append(bikeB)
        self.bike_list.append(bikeC)

    def info_bike(self):
        for bike in self.bike_list:
            bike
        input('请按任意键继续:')
m1 = Manage()
m1.menu()

尝试运行后,收到了系统的错误提示:使用__init__不能设置返回值。先讲这句话换成print(‘车辆编号%d 已经运行%d年,车辆状态:%s’ % (self.NO, self.age, status)),通过单步运行发现,键入1时没有任何打印结果,bike只是收纳了地址,但并没有执行地址对应的内容。
为了解决以上的问题,我们引入另一种方法:
__str __ ()方法
__str __()方法与 初始化方法__init __()有些类似,它也有特殊功能,那就是当这个方法在接触到print函数时,这个方法会自动执行并最终打印该方法的返回值,但他的返回值必须是字符串类型。下面我们举例介绍:

class Bike:
    def __str__(self):
        return 'a'
# bike存储的是一个地址量,通过这种方式可以让代码在
# 找到对应位置后继续运行代码打印返回的内容
bike=Bike()
print(bike)
#运行结果:a

而如果我们设置别的方法,就会打印出实例bike存储的地址:

class Bike:
    def str(self):
        return 'a'
bike=Bike()
print(bike)
# 运行结果:<__main__.Bike object at 0x0000015A2CCF70F0>

用这个方法就可以让我们存储好的地址应用起来:

class Bike:
    def __init__(self, NO, age, state=0):
        self.NO = NO
        self.age = age
        self.state = state
    def __str__(self):
        if self.state == 0:
            status = '待租借'
        else:
            status = '租借中'
        return '车辆编号%d 已经运行%d年,车辆状态:%s' % (self.NO, self.age, status)
class Manage:
    bike_list = []

    def menu(self):
        print("欢迎使用共享单车租借系统\n")
        while True:
            print('1.查询所有车辆\n 2.共享车辆\n 3.租借车辆\n 4.归还车辆\n 其他任意键.退出系统\n')
            try:
                select = int(input('请输入所需功能对应按键'))
                # 按1跳转车辆信息并输出
                if select == 1:
                    self.info_bike()
                else:
                    print('期待您下次使用!祝您生活愉快!')
                    break
            except ValueError:
                print('期待您下次使用!祝您生活愉快!')
                break

    def __init__(self):
        bikeA = Bike(1001, 2)
        bikeB = Bike(1002, 2)
        bikeC = Bike(1003, 1)
        self.bike_list.append(bikeA)
        self.bike_list.append(bikeB)
        self.bike_list.append(bikeC)

    def info_bike(self):
        for bike in self.bike_list:
            print(bike)
        input('请按任意键继续:')
m1 = Manage()
m1.menu()

哟偶兴趣的小伙伴可以运行一下看看结果
按键2对应方法
上文我们详细分析了按键1的详细处理方法,下面我们对按键2进行完善。按下按键2可以将车辆信息上传到系统,因此,我们给Manage类加一个方法,在select==2的时候调用:

def add_bike(self):
	new_number = int(input('请输入共享新车的编号:'))
	new_age = int(input('请输入共享新车的使用年限:'))
	new_bike=Bike(new_number,new_age)
	# 将新车的信息也存入属性列表,系统也就录入了新车信息
	self.bike_list.append(new_bike)
	print('共享成功!')
	input('请按任意键继续')

按键2的处理由于和按键1很像,所以处理起来相对简单。
按键3对应方法
下面我们处理租借车辆的操作。想要租借车辆,需要输入车辆编号,然后在系统中找到对应编号的车,如果该车辆已经处于租借状态则给出对应提示,如果这辆车没有被租借则将其状态改为租借中(默认参数state置1)。为Manage类添加一个新的方法:

def lease_bike(self):
    lease_NO = int(input('请输入想租借的自行车编号:'))
    i = 1
    # 设置计数器i
    for bike in self.bike_list:
        if bike.NO == lease_NO:
        # 利用地址信息找到类的NO属性并进行对比
        # 如果找到对应编号则执行以下操作:
            if 1 == bike.state:
           # state标记为1,这辆车已经被租借走
                print('你来晚了,这辆车已经被借走了。')
                sel = int(input('请按1继续租借其他车辆或其他任意键返回:'))
              # 让使用者自行选择返回或租借其他车辆
                if 1 == sel:
                    self.lease_bike()
                    break
                else:
                    break
            else:
          # state标记为0,该车辆处于待租借状态
                bike.state = 1
              # 将state标记为1,状态改为租借中
                print("租借成功,欢迎您使用绿色出行!")
                break
	# 在列表中没有找到想租借的车辆序号,此时会给出提示并返回
        elif len(self.bike_list) == i:
            print('抱歉,没有找到你想租借的车辆!')
            break
      # 计数器防止程序只运行一次就退出
        i += 1

这样,按键3的细节就处理完成了。
按键4对应方法
按键4的处理与按键3类似,只需要将state改为1便可。不再赘述:

def revert_bike(self):
    revert_NO = int(input("请输入归还的车辆编号:"))
    i = 1
    for bike in self.bike_list:
        if bike.NO == revert_NO:
            if 1 == bike.state:
                # state为1,这辆车处于租借状态
                bike.state = 0
                print('还车成功!')
                input('请按任意键继续')
            else:
                # state为0,该车辆处于待租借状态
                 print("车辆状态为待租借,无需归还")
                sel = int(input('请按1继续租借其他车辆或其他任意键返回:'))
                # 让使用者自行选择返回或重新输入车辆编号
                if 1 == sel:
                    self.revert_bike()
                    break
                else:
                    break
        # 在列表中没有找到想还的车辆序号,此时会给出提示并返回
        elif len(self.bike_list) == i:
            print('该车辆不存在,想必您是输错了!')
            input('请按任意键返回')
            break
        i+=1

通过观察发现,用这种方式实现,按键3和按键4的处理上会有相当长的重复性代码,即遍历整个属性列表寻找输入的自行车编号。因此,我们可以设置新的方法来存储着一段代码,仅在按键3和4内对这个新方法进行调用,新方法如下:

def select_bike(self,NO):
    #遍历整个自行车列表
    for bike in self.bike_list:
        #如果存在输入编号与车辆列表中的编号一致
        if bike.NO == NO:
            #返回该地址
            return bike

3)各按键功能实现的代码合并

以上,我们已经详细拆解了共享单车租借平台的各个模块,下面我们将其整合起来,并运行测试:

class Bike:
    def __init__(self, NO, age, state=0):
        self.NO = NO
        self.age = age
        self.state = state
    def __str__(self) :
        if self.state == 0:
            status = '待租借'
        else:
            status = '租借中'
        return '车辆编号%d 已经运行%d年,车辆状态:%s' % (self.NO, self.age, status)

class Manage:
    bike_list=[]
    def __init__(self):
        bikeA = Bike(1001, 2)
        bikeB = Bike(1002, 2)
        bikeC = Bike(1003, 1)
        self.bike_list.append(bikeA)
        self.bike_list.append(bikeB)
        self.bike_list.append(bikeC)
    # 按键1功能实现
    def info_bike(self):
        for bike in self.bike_list:
            print(bike)
        input('请按任意键继续:')
    # 菜单函数显示按键提示,并进行对应跳转

    # 按键2功能实现
    def add_bike(self):
        new_number = int(input('请输入共享新车的编号:'))
        new_age = int(input('请输入共享新车的使用年限:'))
        new_bike = Bike(new_number, new_age)
        # 将新车的信息也存入属性列表,系统也就录入了新车信息
        self.bike_list.append(new_bike)
        print('共享成功!')
        input('请按任意键继续')

    # 遍历列表寻找车辆,为按键3/4的实现做前期准备
    def select_bike(self,NO):
        #遍历整个自行车列表
        for bike in self.bike_list:
            #如果存在输入编号与车辆列表中的编号一致
            if bike.NO == NO:
                #返回该车辆信息
                return bike

    # 按键3功能实现
    def lease_bike(self):
        lease_NO = int(input('请输入想租借的自行车编号:'))
        bike = self.select_bike(lease_NO)
        if 1 == bike.state:
            # state标记为1,这辆车已经被租借走
            print('你来晚了,这辆车已经被借走了。')
            sel = int(input('请按1继续租借其他车辆或其他任意键返回:'))
            if 1 == sel:
                self.lease_bike()
        else:
            bike.state = 1
            print('租借成功,欢迎您使用绿色出行!')
            input('请按任意键继续')
            # 让使用者自行选择返回或租借其他车辆

    # 按键4功能实现
    def revert_bike(self):
      # 输入归还车辆的编号
        revert_NO = int(input("请输入归还的车辆编号:"))
      # 进行查询
        res = self.select_bike(revert_NO)
      # 车辆存在
        if res != None:
          # 租借中,可以还车
            if res.state ==1:
                # 还车成功
                res.state = 0
                print("还车成功,期待下次使用")
                input('请按任意键继续')
        # 未租借,等待租借
            else:
              # 车辆等待租借
                print("车辆状态为待租借,无需归还")
                input('请按任意键继续')
        # 车辆不存在
        else:
            print("该车辆不存在,想必您是输错了")
            input('请按任意键继续')
	# 菜单栏打印
    def menu(self):
        print("欢迎使用共享单车租借系统\n")
        while True:
            print('1.查询所有车辆\n 2.共享车辆\n 3.租借车辆\n 4.归还车辆\n 其他任意键.退出系统\n')
            try:
                select = int(input('请输入所需功能对应按键'))
                # 按1跳转车辆信息并输出
                if select == 1:
                    # 输出单车信息
                    self.info_bike()
                # 按2跳转向系统内输入单车信息
                elif select == 2:
                    # 进行共享单车操作
                    self.add_bike()

                # 按3跳转租借车辆
                elif select == 3:
                    # 进行租借操作
                    self.lease_bike()
                # 按4跳转归还车辆
                elif select == 4:
                    # 进行归还操作
                    self.revert_bike()
                # 按其他任意键退出系统
                else:
                    print('期待您下次使用!祝您生活愉快!')
                    input('请按任意键继续')
                    break
            except ValueError:
                print('期待您下次使用!祝您生活愉快!')
                input('请按任意键继续')
                break
me=Manage()
me.menu()

到此,这道编程题正式结束。

三、面对过程编程与面对对象编程对比

以上,我们进行了面对过程编程和面对对象编程实例分析,下面就来进行两种编程方式的对比:
面对过程编程依靠的是结局问题的具体步骤逐步完成编程,需要分析出解决问题的步骤,及首先干什么,然后干什么,最后干什么;
面对对象编程不考虑实现功能的步骤,而是考虑实现这个功能需要设计什么样的类,这个类中有哪些属性和方法,然后通过这个类创建一个实例对象,让对象来调用类属性与类方法。

面对过程编程面对对象编程项目
特点以过程为中心以对象为中心
内容函数的创建和调用类的创建和调用
程序组成一系列过程的集合一组对象的集合

这次的分享就到这里啦,新来的小伙伴点赞支持一下再走呗~