本文介绍的作品是全国青少年创意编程与智能设计大赛创意编程比赛王梓名同学的参赛作品。
作品说明
一个记录朋友生日的小程序,数据来源于本地csv文件,简单好用,希望大家喜欢,也欢迎提供宝贵的意见。
正文
今天,果冻老师和大家一起来学习王梓名同学开发的Python小作品,叫做《智能生日提示小助手》,不知道大家有没有这样的烦恼,好朋友和同学太多了,要记住每个同学的生日真是一件头疼的事情。如果有一个可以帮助我们记录同学生日的程序那会很有用的,王梓名同学就开发了这么一款工具,简单方便,下面我们就看看它是如何实现的吧。
引入代码库
生日小助手工具一共用到了三种代码库,分别是csv、tkinter、datetime。
这三个代码库都是Python环境自带的模块,不需要单独下载,可以直接引入使用。tkinter模块在上一个《自主数学练习小工具》作品中有介绍过,它可以实现一个图形化的操作界面,我们可以使用鼠标点击、拖动等方式与程序进行交互,这种操作方式更加的直观,更人性化。
csv和datetime模块我们第一次见到,它们是干什么的呢?老师分别来介绍一下。
csv,全称叫做Comma-Separated Values,中文称为逗号分隔值文件格式,因为这种格式的文件存储的数据是用逗号分隔开的,比如果冻老师用电脑的记事本打开保存朋友生日的csv文件,是这样的:
文件中的每一行代表一组数据,每组数据都需要输入姓名和身份证号,它们之间用逗号隔开。在Python中我们通过引入csv模块,并使用模块中的函数就可以读取这个文件中的内容,也可以给文件写入内容,这其实就是一种最简单的数据库,有了数据库呢,我们就可以实现真正的注册登陆功能,也可以在程序中将本次添加的内容记录下来,下次打开程序继续完善,这不就是便签的功能吗?把身份证号换成手机号还能实现一个通讯录,这下Python代码如虎添翼,可以发挥的想象空间就太多了!
第二个模块呢,叫datetime,date英文翻译过来就是日期,time英文翻译过来是时间,datetime就是Python中用于处理日期和时间的模块,我们需要它来获得今天的日期,然后再与每个小朋友的生日对比,选出过生日的同学的姓名。
OK,模块介绍完了,接下来我们就要进入核心的生日判断函数了。
定义函数
生日提示助手程序的所有功能都定义在这个叫做find_birthday的函数中,find的意思是查找,birthday大家都知道意思是生日。在这个函数里面会读取csv文件中的生日信息,然后显示在程序的界面上。
和数学练习小工具一样,第一步,需要实例化tkinter对象。
实例化之后,就可以通过title( )函数和geometry( )函数来设置窗口的名称与大小。
第二步,获取今天的时间,并取出月份和日期。
第一行,date.today( ),英文today的中文意思是今天,所以通过这行代码就可以获取到当前的日期,并且保存在now这个对象变量中,如果我们在第一行的代码下面加上print(now),就可以看到now对象中保存的数据:
这就是电脑系统中最常见的日期格式,表示“年-月-日”,每个数字之前用“-”隔开,由于老师写这篇文章的时间是4月7号,所以now变量中存储的就是2020年4月7日。
日期对象中还有三个属性:year,month,day,它们可以从now这个时间对象中分别取出年、月、日这三种数据,在生日提示助手中需要用到月和日这个数据,所以在代码中可以通过now.month和now.day来分别获得,并且使用str( )函数将它们转换成字符串,最后保存在this_month和this_day这两个变量中,以供后面使用。
这里有一个小问题,如果我们使用print( )函数打印出this_month和this_day两个变量的值,就能看到它们分别保存的是数字4和7。可是,后面我们是要用它们和身份证号进行比对的,同学们看一下自己的身份证号就会发现如果代表生日月和日的这两个数字是一位数的话,会在数字的前面加上0,于是,在代码中我们同样也要处理一下。
比如说月和日变量的长度都是一,那么就给它们的前面加上“0”,这时,this_month和this_day中分别保存的就是“04”和“07”了。
第三步,循环读取“花名册.csv”这个文件中每个小朋友的身份证号,并取出月与日的值,与上面的两个变量进行对比,最后判断出是否有小朋友在过生日。
要注意的是,花名册.csv这个文件和程序的代码文件放在同一个目录中,然后我们通过open( )函数来直接打开花名册。细心的同学发现了,打开文件的open('花名册.csv')代码放在with...as f这条语句的中间,那这个with...as...结构的代码是干什么的呢?这个要解释起来稍稍有些复杂,大家只需要记住这样写可以帮助我们简化代码,因为操作一个文件本来要经过五个步骤,第一步,打开文件,第二步,如果文件不存在,要处理异常,第三步,读取文件,第四步,如果读取文件发生异常,则处理它,最后一步,关闭打开的文件。而在Python中这些步骤可以简化写成with...as...结构代码,无论会不会抛出异常,程序都会在最后自动关闭文件。
打开文件之后呢,当然就要读取文件中的内容了。读取csv文件需要使用csv.reader( )语句,括号中传入with...as...结构中as后面的变量f,这样就创建了一个reader对象,并赋给content。
有了reader对象,我们循环遍历它,然后就能取出csv文件中每行的数据了。在继续下面的代码前,老师先print(q)打印一下q变量的值看看它是什么样子的。
哈,原来csv文件中的每一行都变成了一个列表,那接下来的操作你应该就很熟悉了。
首先,取出身份证号中代表月份的两位数字,q[1]表示获取逗号后面身份证号的整体值,再加上一个方括号q[1][-8:-6]就表示身份证号从右往左数第8位到第7位的两个数字,以王小明为例,这个数字就是“04”,将它保存在变量birthday_month中。
接着,取出身份证号中代表日期的两位数字,紧跟着月份后面的两位数字就是了,代码就是q[1][-6:-4],并赋给birthday这个变量。
好,有了身份证中的月份和日期,上面我们还获得了当天的月份和日期,接下来,只要比较一下它们,相等的话就将这个小朋友的名字显示在屏幕上。
在程序的窗口中如何显示文字,在上一篇数学练习小工具中讲过,使用tkinter模块中的Label控件,控件的text属性用于设置显示的文本,这里我们用+号将小朋友的姓名和生日拼接在一起,bg属性用于设置标签的背景颜色,font属性设置文字的字体和大小,width和height属性设置标签的宽度和高度。
与数学练习小工具不同的是,上一篇文章中各种控件的排列使用的是grid布局, 而在生日提示程序的界面中使用的是pack布局,那什么是pack布局呢?很简单,在pack( )函数不带任何参数的情况下,设置为pack布局的控件就是从上到下按顺序依次排列的。
代码中紧接着又定义了一个Label控件,这次它没有使用pack布局,而是用了另外的一个place布局,place布局相比起来更加的灵活,它允许设置一个x,y坐标来定义控件在界面上显示的位置。这里我们把label_2放在x=250,y=380的这个坐标点上,也就是程序界面的右下角。
grid布局、pack布局和place布局是tkinter模块中支持的三种布局方式,我们在上一篇文章和本篇文章中全都学习到了,果冻老师讲解的比较简单,如果想深入的了解每种布局方式的使用细节,你可以在网上搜索自己先了解。
函数的最后一行,调用tkinter模块的mainloop( )函数,程序窗口就可以正常的显示出来啦。
到这里,生日提示小助手中最重要的也是唯一的一个函数就定义好了。
那程序的最后一行应该写什么呢?当然就是调用这个函数的代码:
快快运行起程序,看看最终的效果吧!
小助手提示我们,今天是王小明同学的生日哦!
生日提示小助手的代码就是这样子,不知道同学们有没有意犹未尽的感觉?老师总是感觉差了点什么,是什么呢?仔细想了想,原来这个生日小助手的提示功能有点鸡肋呀,因为如果到生日当天才去提醒,那一切都晚了,连给朋友准备生日礼物的时间都没有。假如可以提醒每个人的生日还有多少天,那就合理多了,我们可以在快过生日的时候提前给朋友准备好礼物。
OK,果冻老师接下来就继续完善这个作品,让它可以显示每个人生日的剩余天数。
增加剩余天数
要计算剩余的天数,就需要获取到每个同学身份证号中的生日日期以及当天的日期。当天的日期我们已经通过date.today( )获取到了,就是now变量中保存的数据。而身份证号中月和日也已经取出来了,剩下只需要将年份拼接起来,就可以组成生日的日期了。
要注意,每个人生日的年份要使用当前的年份,而不是身份证号中的,接着将年、月、日作为参数传到date( )函数中,就得到了我们需要的日期。
接下来,将每个人的生日减去当前的时间,就可以得到一个差值,这个差值包含两个日期相差的天数和时间,我们只需要天数的值,于是,再通过interval.days进行过滤,inte_days变量里面保存的就是最终的数据了。
但是,这里有一个问题,就是如果某个小朋友今年的生日已经过了,那么与当前日期的差值就会是一个负数,这种情况下,我们就需要计算这个小朋友明年的生日日期与当前日期的差值,于是,代码中就多了一个if条件判断:
当差值小于0时,date( )函数中的第一个参数传入+1的年份。
最后,把inte_days这个变量拼接到字符串中,最终的程序就改造完成了。
总结
通过《智能生日提示小助手》这个作品的学习,我们了解了在Python中如何读取csv格式的文件内容和日期的获取方法。读写文件是Python开发中非常有用的一种操作,用于保存少量非保密的数据是非常方便的,除了csv,常见的文件格式还有txt,xml,不同的文件格式保存数据的格式要求也是不一样的,在后面的作品中果冻老师会逐个讲解到。那这节课也交给你一个小任务,就是改造这个生日助手程序,开发一个通讯录的工具,在文件中保存好姓名和手机号,然后在软件的界面上用列表显示出来。当然,你也可以更进一步,自己在网上搜索一下往文件中写文件的方法,然后再增加一个添加手机号的功能,这样,就是一个完整的通讯录软件了。