python实现简易的可视化计算器,软工第一次作业(102101343)

本文详细描述了一个使用Python和Tkinter实现的简易计算器的开发过程,包括界面设计、功能实现、Gitcode项目地址、性能改进、单元测试和异常处理措施。作者通过实例展示了从需求分析到代码实现的完整流程。
摘要由CSDN通过智能技术生成


作业基本信息

这个作业属于哪个课程< 2301-计算机学院-软件工程>
这个作业要求在哪里< 软工实践第一次作业>
这个作业的目标< 实现一个简易计算器的功能,能有可视化的界面运行 >
其他参考文献< Python_GUI教程(1) Python_GUI教程(2)

解题思路描述

  • 实现一个计算器的功能我是考虑由最简单的加减乘除入手,我选择了我稍有了解的python语言进行解题,我基于tkinter库进行界面化设计,用tkinter库自带的按钮(Button)、标签(Label)等类完成可视化界面。

  • 计算功能我则是通过python自带的eval()函数以字符串拼接的形势进行运算,对不同的运算符进行判断从而实现各个的效果。

  • 解题过程大概为 先实现简单加减乘除与初步的界面,完成后进一步设计三角函数等扩展功能,最后通过通过代码调试等进行改良优化。

Gitcode项目地址

Python实现简易可视化计算器

效果展示

计算式1
计算式2

PSP表格

PSPPersonal Software Process Stages预估耗时(分钟)实际耗时(分钟)
Planning计划3035
• Estimate• 估计这个任务需要多少时间1525
Development开发300420
• Analysis• 需求分析 (包括学习新技术)6060
• Design Spec• 生成设计文档3020
• Design Review• 设计复审3025
• Coding Standard• 代码规范 (为目前的开发制定合适的规范)2020
• Design• 具体设计4035
• Coding• 具体编码150200
• Code Review• 代码复审5030
• Test• 测试(自我测试,修改代码,提交修改)60150
Reporting报告120100
• Test Repor• 测试报告100130
• Size Measurement• 计算工作量1010
• Postmortem & Process Improvement Plan• 事后总结, 并提出过程改进计划10090
合计11151350

接口设计和实现过程

1、创建并初始化计算器类Cal(),

  • label1为缓存运算中的数字的标签(不显示在界面上)
  • label2是实时显示运算过程的标签
  • label3是显示运算结果的标签
  • list是储存用于eval()函数运算的字符串表达式
  • op_type储存字符串运算表达式中缺少右括号的数量
class Cal():
    def __init__(self, init_window_name):
        self.init_window_name = init_window_name
        self.label1 = StringVar() # 缓存运算中的数字的标签(不显示)
        self.label1.set('0')
        self.label2 = StringVar()	# 实时显示运算过程的标签
        self.label2.set('result=0')
        self.label3 = StringVar()	# 显示运算结果的标签
        self.label3.set('0')
        self.list = []				# 储存需要运算的字符串表达式
        self.op_type = 0			# 作为标记运算中括号的变量

2.input_num()函数是对数字按钮(0~9)进行处理,初始为0则进行替代,不为0则将已存的数字与新的数字进行拼接,同时实时更新显示标签

    def input_num(self,num):	# 对数字按钮的处理
        temp = self.label3.get()
        if temp == '0':			# 对实时显示的标签进行更新
            self.label3.set(num)
        else:
            self.label3.set(temp+num)
        t_num = self.label1.get()
        if t_num == '0':		# 对缓存数字的标签进行更新
            self.label1.set(num)
        else:
            newnum = t_num + num
            self.label1.set(newnum)

3.对各类运算符进行处理(因为分支较多,此处仅展示部分)

    def input_sign(self, sign):
        num = self.label1.get()
        temp = self.label3.get()
        if temp == '0':
            temp = ''
        if self.op_type == 0:
            if sign == 'Clear':		# 实现归0,将所有变量恢复初值
                self.list.clear()
                self.label1.set('0')
                self.label3.set('0')
                self.op_type = 0
            elif sign == 'sin':	    #实现三角函数中的san(),将字符串“sin(”拼接到list中储存,后面在eval()函数进行运算
                if num != '0':
                self.list.append(num)
                self.list.append('sin(')
                self.label3.set(temp+'sin(')
                self.label1.set('0')

4.将储存起来的字符串表达式通过eval()函数进行运算,并利用try语句进行异常处理

    def result(self):
        t_num = self.label1.get()
        if t_num!= '0':
            self.list.append(t_num)
        self.label1.set('0')
        while self.op_type != 0:	# 此循环目的在于将缺的右括号补上
            self.list.append(')')
            self.op_type -= 1
        cal_Str = ''.join(self.list)
        endNum = 0
        try:
            endNum = eval(cal_Str)
            if isinstance(endNum, int):
                self.label2.set("result={:.0f}".format(endNum))
            else:
                self.label2.set("result={:.02f}".format(endNum))
        except (ZeroDivisionError):
            self.label3.set("计算过程发生除零错误!")
        except (SyntaxError):
            self.label3.set("错误:缺少括号!")
        except:
            self.label3.set("计算过程发生错误!")

        return endNum

关键代码展示

以下代码为input_sign()函数中运算符为±*/.的情况,通过对label1、label2、list、op_type四个变量的操作实现

            else:					# 运算符为+-*/.的情况
                if num != '0':		# label1中存缓存的数字不为0则就加到list中
                    self.list.append(num)  
                while self.op_type != 0:	# 在'^'的按钮中会op_type会加1,表示表达式欠缺的')'数量,此处通过while循环补全,能够让表达式表示正确和实现次方的次方
                    self.list.append(')')
                    self.op_type -= 1
                if sign == '*':				# 对乘法运算显示的'*'替换为'X'
                    self.label3.set(temp+"X")
                else:
                    self.label3.set(temp+sign)
                self.list.append(sign)
                self.label1.set('0')

性能改进与优化

  • 一开始编写代码中在input_sign()函数里分为op_type是否为0的两种情况进行讨论(即表达式是否缺少右括号),但后续优化中发现两种情况的操作可以归为一类,无需用if语句进行选择判断
if self.op_type == 0:
	if sign == 'Clear':
         self.list.clear()
         self.label1.set('0')
         self.label2.set('result=0')
         self.label3.set('0')
         ……
         
else:
    if sign == 'Clear':
         self.list.clear()
         self.label1.set('0')
         self.label2.set('result=0')
         self.label3.set('0')
         ……

单元测试

本次使用python的unittest库进行单元测试,通过了五个测试函数进行测试,包括了加减乘除、次元、三角函数等混合操作进行了测试,结果如下:

p1

单元测试代码的五个测试函数如下:

root = Tk()
class TestCalculator(unittest.TestCase):
    def test1(self):
        cal = Cal(root)
        cal.list = "1+7*2+4/2"
        r = cal.result()
        self.assertEqual(r, 17)

    def test2(self):
        cal = Cal(root)
        cal.list = "1024+0.99+2.5/2"
        r = cal.result()
        self.assertEqual(r, 1026.24)

    def test3(self):
        cal = Cal(root)
        cal.list = "sin(pi/2)+1.44"
        r = cal.result()
        self.assertEqual(r, 2.44)

    def test4(self):
        cal = Cal(root)
        cal.list = "1+sin(pi/2)+pow(2,2)"
        r = cal.result()
        self.assertEqual(r, 6)

    def test5(self):
        cal = Cal(root)
        cal.list = "8*tan(pi/4)+pow(2,pow(2,2))"
        r = cal.result()
        self.assertEqual(r, 24.0)

if __name__ == '__main__':
    unittest.main()

异常处理措施与展示

采用python的try操作进行异常处理

        try:
            endNum = eval(cal_Str)
            if isinstance(endNum, int):
                self.label2.set("result={:.0f}".format(endNum))
            else:
                self.label2.set("result={:.02f}".format(endNum))
        except (ZeroDivisionError):
            self.label3.set("计算过程发生除零错误!")
        except (SyntaxError):
            self.label3.set("错误:缺少括号!")
        except:
            self.label3.set("计算过程发生错误!")
  • 异常处理展示
    除零错误
    缺少括号

体会与总结

  • 通过本次实现可视化计算器的过程,我大致感受到完成一个项目所需的流程 , 在开发前进行计划和需求分析,开发时编写代码、满足需求、设计文档,在开发后进行单元测试、bug调试等。
  • 通过此次作业我处理需求和设计代码的能力有所提升,能更好的根据需求来编写、设计软件
  • 基本熟悉了Pythontkinter库的使用方式和流程,并能基于此完成简单的可视化软件编程
  • 不断编写代码过程中提高了我debug的能力,处理bug比起以前能更加从容。
  • 学会了如何进行单元测试和异常处理,对于改进和优化程序的了解更进一步。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值