#20214302单宇航 《Python程序设计》实验报告

 # 20214302单宇航 2021-2022-2 《Python程序设计》实验二报告

课程:《Python程序设计》
班级: 2143
姓名: 单宇航
学号:20214302
实验教师:王志强
实验日期:2022年4月5日
必修/选修: 公选课

## 1.实验内容
1).计算并完成一个完整的应用程序,完成加减乘除模等运算,功能多多益善
2).考核基本语法、判断语句、循环语句、逻辑运算等知识点
## 2. 实验过程及结果

# 计算器

# 第一部分——导入库和库函数
import os
import re
import tkinter as tk #导入tkinter模块
import random
import tkinter.messagebox
from math import * #从Python标准库引入math.py模块。

# 第二部分——对窗口、文本框的设置
root = tkinter.Tk() # 新建窗口
root.geometry("300x460+450+150") # 设置窗口的大小和位置(第一个是窗口的宽度,第二个是窗口的高度,第三个是左上角窗口距离屏幕边界距离)
root.resizable(0, False) # 该指令设定窗口界面宽、高不可变,括号内0或False均可。
root.title("计算器") # ()括号内添加窗口标题
contentVar = tkinter.StringVar(root, "") # 在根窗口中建新一个以contentVar为控制变量的文本框,类型为可变文本框
# tkinter中,Entry表示单行文本框,Text表示多行文本框
# 用textvariable设置为可变文本,与StringVar可变文本框等配合使用
contentEntry = tkinter.Entry(root, textvariable=contentVar) # 将文本框状态设置为正常,即允许在文本框中进行键盘输入
contentEntry["state"] = "normal"
contentEntry.place(x=10, y=10, width=280, height=20) # 设置文本框的位置,宽度和高度
# 第三部分——放置菜单和按钮
# (1)第一小部分放置按钮
# command=函数名,传递给command属性的是函数对象,函数名后面不能加括号,也不能传递函数。而执行相应的操作,需要对不同参数进行处理,
# 故需要重新定义一个函数,让这个函数调用另一个函数
# lambda是一种快速定义的最小函数(单行)
# 注意:lambda 函数可以接收任意多个参数 (包括可选参数),并且返回单个表达式的值。
# lambda 函数不能包含命令,包含的表达式不能超过一个。
btnClear = tkinter.Button(root, text="Clear", command=lambda: buttonClick("Clear")) # 放置清空Clear按钮。
btnClear.place(x=20, y=40, width=50, height=20) #设置按钮坐标、宽度和高度。
btnDel = tkinter.Button(root, text="Del", command=lambda: buttonClick("Del")) # 放置删除Del按钮。
btnDel.place(x=90, y=40, width=50, height=20) #设置按钮坐标、宽度和高度。
btnCompute = tkinter.Button(root, text="=", command=lambda: buttonClick("=")) # 放置等号按钮。
btnCompute.place(x=230, y=40, width=50, height=20) #设置按钮坐标、宽度和高度。
btnHelp = tkinter.Button(root, text="帮助", command=lambda: buttonClick("帮助")) # 放置帮助按钮。
btnHelp.place(x=230, y=350, width=50, height=50) #设置按钮坐标、宽度和高度。
btnQuit = tkinter.Button(root, text="退出", command=lambda: quit()) # 放置退出按钮。
btnQuit.place(x=230, y=430, width=50, height=20) #设置按钮的坐标、宽度和高度。
# 放置()[]按钮
signs = ["(",")","[","]"] #设置signs的列表
number = 0 #循环开始数为0
for sign in signs: #让signs列表的内容一个一个循环输出。
number += 1 #number计数+1
btnDigist = tkinter.Button(root, text=sign, command=lambda x=sign: buttonClick(x)) #设置(,),[,]四个按钮的位置
btnDigist.place(x=155 + 15 * number, y=40, width=14, height=20) #设置按钮的坐标,宽度和高度。

# 放置0123456789十个数字,小数点,计算平方根,调用三角反三角函数以及随机数的按钮
digists = list("012345678.9,") + ["sin(", "cos(", "tanx(", "asin(", "acos(",
"atan(", "Sqrt", "ceil(", "floor(", "abs(", "随机数","#"]
index = 0
for row in range(8):
for col in range(3):
d = digists[index]
index += 1
btnDigist = tkinter.Button(root, text=d, command=lambda x=d: buttonClick(x))
btnDigist.place(x=20 + col * 70, y=80 + row * 50, width=50, height=20) #用for循环,将以上按钮一个一个按顺序设置

# 放置运算符按钮和π,e以及数学常数τ的近似值按钮(同上)。
operators = ("+", "-", "*", "/", "**", "//", "π", "e", "tau")
for index, operator in enumerate(operators):
btnOperator = tkinter.Button(root, text=operator, command=lambda x=operator: buttonClick(x))
btnOperator.place(x=230, y=80 + index * 30, width=50, height=20)

# (2)第二小部分放置菜单

m = tkinter.Menu(root)
root.config(menu=m)
# 设置file选项
filemenu = tkinter.Menu(m)
m.add_cascade(label="File", menu=filemenu)
filemenu.add_command(label="New", command=lambda: callback("New"))
filemenu.add_separator()
filemenu.add_command(label="History", command=lambda: callback("History"))
filemenu.add_separator()
filemenu.add_command(label="Exit", command=lambda: quit())
filemenu.add_separator()
filemenu.add_command(label="top", command=lambda: root.wm_attributes("-topmost", 1))
filemenu.add_separator()
#在此做一个补充,例如filemenu,flie是菜单menu标题的名字,"New,History,Exit,top"为file菜单中的包含项目。
# 设置help选项(同上)
helpmenu = tkinter.Menu(m)
m.add_cascade(label="Help", menu=helpmenu)
#对help菜单进行补充,方式同上面数字按钮,利用的for对于列表list的循环
list = ['pi', 'e', 'tau', 'asin', '//', '**', "sqrt", "随机数"]
list_explain = ["pi:圆周率π的近似值", "e:自然对数e的近似值", 'tau:数学常数τ的近似值',
"""asin,acos,atan,分别代表反三角函数:
arcsin,arccos,arctan""", "/:表示除号,//:表示整除", "*:表示乘号,**:表示乘方",
"Sqrt:表示开方", "随机数:random.randint(x,y),将生成一个在区间[x,y]之间的随机整数"]
index = 0
help_dict = {}
for i in list:
helpmenu.add_command(label=i, command=lambda x=i: callback(x))
help_dict[i] = list_explain[index]
index += 1
# 第四部分——按钮处理代码和菜单处理代码

# (1)第一小部分按钮处理代码

def buttonClick(btn):
# 获取录入框中的文本内容,def作用是调用函数
content = contentVar.get()
# 根据不同的按钮,做出相应的处理
# 如果已有内容时以小数点开头的,前面加0
if content.startswith("."):
content = "0" + content + btn
# 如果参数为Clear,清空文本框,如果参数为Del,去除最后一个字符
elif btn == "Clear":
content = ""
elif btn == "Del":
content = content[:-1]
# 如果新输入字符串btn是小数点,且字符串content的个数大于1并以运算符结尾时,在小数点前加0;
# 以数字结尾时,添加小数点,以ieu,结尾时报错,不对文本框内容做修改
elif btn == "." and len(content) >= 1:
if content[-1] in "()[]+-*/":
content = content + "0."
elif content[-1] in "0123456789":
content += btn
elif content[-1] in "π,eτ":
tkinter.messagebox.showerror("错误:", "π,eτ后不能有小数点")
return
# 如果参数在"0123456789,()[]sin(cos(tan(pietauasin(acos(atan(ceil(floor(abs("之中,
# 在文本框末尾直接加入此参数
elif btn in "0123456789,()[]sin(cos(tan(pietauasin(acos(atan(ceil(floor(abs(":
content += btn
# 如果参数为帮助,则弹出帮助提示界面,内含相关按钮介绍及使用方法
elif btn == "帮助":
tkinter.messagebox.showinfo("帮助", """ pi:圆周率π的近似值
e:自然对数e的近似值
tau:数学常数τ的近似值
asin,acos,atan,分别代表反三角函数:
arcsin,arccos,arctan
/:表示除号
//:表示整除
*:表示乘号
**:表示幂(次方)
Sqrt:表示开方
Clear:表示清空数据
del:表示退格,相当于电脑上的Backsace键
随机数:random.randint(x,y),将生成一个在区间[x,y]之间的随机整数""")
#
elif btn == "随机数":
content += "random.randint("
elif btn == "=":
try:
# 对输入的表达式求值,并写入文件
# 获取当前文件所在的路径
pdw = os.getcwd()
outfile = open(pdw + "\\history.txt", "a")
outfile.write(content)
content = str(round(eval(content), 10))
outfile.write("=" + content + "\n")
outfile.close()
except:
tkinter.messagebox.showerror("错误", "表达式错误")
return
elif btn in operators:
if content.endswith(operators):
tkinter.messagebox.showerror("错误", "不允许连续运算符")
return
content += btn
# 如果参数为Sqrt,则
elif btn == "Sqrt":
try:
content = eval(content) ** 0.5
except:
tkinter.messagebox.showerror("错误", "表达式错误")
contentVar.set(content)


# (2)第二小部分菜单处理代码

def callback(btn):
content = contentVar.get()
if btn == "New":
content = ""
elif btn in list:
tkinter.messagebox.showinfo("Help", help_dict[btn])
return
contentVar.set(content)
# 第五部分——进入主循环

# 进入主(消息)循环,准备处理事件(必须组建),除非用户关闭窗口(或者按退出键),
# 否则程序将一直处于主循环中
# 注意:只有进入了主循环,窗口才可见
root.mainloop()


## 3. 实验过程中遇到的问题和解决过程
- 问题1:有思路,不知道如何写代码
- 问题1解决方案:上网查询,向同学询问
- 问题2:许多代码并未见过
- 问题2解决方案:一次一次尝试,不断改动变量,寻找新代码的使用方式



## 上课学的知识有限,可以多去看看大佬们的代码,不可能一开始都看得懂,就立马会用,但一定要去多试试。可以一步一步去探索,不会的上网去查,自己尝试,询问老师和同学,见得多了,用于琢磨,就会学到更多新的东西。但是一定要与追求新的知识,不要止步于课上知识和自己现有的知识。python是一个很有趣的世界,只要你肯去探索,实践。

有关该代码的步骤的作用基本已标注在里面,一些知识查询链接也放到参考资料里面了。

## 参考资料

https://www.runoob.com/python/python-for-loop.html

https://www.jianshu.com/p/91844c5bca78

https://blog.csdn.net/weixin_39638014/article/details/109619094

https://blog.csdn.net/m0_37903789/article/details/83622014

https://blog.csdn.net/qq_41563270/article/details/108370160

https://blog.csdn.net/qq_42554007/article/details/122257649

https://blog.csdn.net/m0_37903789/article/details/83622014

https://www.runoob.com/python/att-string-index.html

https://blog.csdn.net/wangyiyan315/article/details/16367551

https://blog.csdn.net/qq_21466543/article/details/81604826

https://blog.csdn.net/lukuanpromise/article/details/83685365

posted @ 2022-04-05 23:21  张家有子名若尘  阅读(145)  评论(0编辑  收藏  举报