所在的位置: 万年县 >> 万年县经济 >> 16练习万年历

16练习万年历

Hi,大家好。我是茶桁。

上一节课最后,我让我家去预习一下日历和时间的相关模块,不知道大家有没有去预习。不管如何,这节课,让我们开始做一个练习:万年历。

没有预习的小伙伴也跟着一起,在本次练习完成的时候,相信你会对这些模块有了初步的了解。

好,让我们开始吧。

首先,我们需要来看看calendar.monthrange()这个函数,它属于calendar模块内,返回指定年份和月份的数据,月份的第一天是周几,和月份中的天数。

importcalendarres=calendar.monthrange(,6)print(res)---(3,30)

我们接收了返回值,但是这个3和30分别是什么意思呢?我们打开日历看一下就明白了:

請輸入圖片文字敘述

如图所见,年的6月份一共是30天,第一天是周四。这也正是(3,30)的含义。之所以是3而不是4,是因为是从0开始计算的,也就是说,周一是0。比如,年5月的第一天就是周一,我们来看看是不是这么回事:

res=calendar.monthrange(,5)print(res)---(0,31)

那有了这个,我们要做一个当月的日历就简单了,还记得我们之前做过一个星星的矩阵吗?是一样的概念,这是这次直接换成了数字而已,来,让我们从最基本框架开始(还是以6月份数据来做):

days=res[1]week=res[0]+1d=1whiled=days:#循环周foriinrange(1,8):print({:02d}.format(d),end="")d+=1print()---

这样,我们就将天数打印出来了。可是,明眼人一眼就看出了问题,这一月只有30天,怎么得到的35天的?让我们来修复一下这个问题:

days=res[1]week=res[0]+1print(一二三四五六日)d=1whiled=days:#循环周foriinrange(1,8):#判断是否输出ifddays:print(,end=)else:print({:02d}.format(d),end="")d+=1print()---一二三四五六日

我们在代码中加了一层判断,如果循环中的d大于days了,那我们就直接输出空格,否则才正确输出格式化的数字,那么这样就可以不输出31-35了。

完成了,顺便还打印了一行星期几。可是问题是,没有和实际情况对齐对吧?没事,我们继续来改动。

days=res[1]week=res[0]+1print(一二三四五六日)d=1whiled=days:#循环周foriinrange(1,8):#判断是否输出ifddaysor(d==1andiweek):print(,end=)else:print({:02d}.format(d),end="")d+=1print()---一二三四五六日

我们在之前判断d大于days的判断上再加上一层,不仅如此,当d==1并且i小于week的时候,也都是出制表符,那自然最开始和最末尾不该出现数字的地方都被制表符补齐了。

我们再来多做一次实验,将月份改成7月来看看和实际情况是否相符,并且,这次我们多加一些内容,将其中的年份和月份也都打印出来:

year=month=7res=calendar.monthrange(year,month)days=res[1]week=res[0]+1print(f========={year}年{month}月=========)print(一二三四五六日)print(=*32)d=1whiled=days:#循环周foriinrange(1,8):#判断是否输出ifddaysor(d==1andiweek):print(,end=)else:print({:02d}.format(d),end="")d+=1print()---=========年7月=========一二三四五六日================================31

我们来看看实际情况是不是如此:

没错,确实如此。7月份的第一天从周六开始,一个月有31天,周一为最后一天。那说明,我们上面写的内容真实有效。

那现在要干嘛呢?当然是封装成一个函数,以year和month为参数,这样,不管我想要查询任意月份,只要我输入对应参数就可以了:

defshowdate(year,month):res=calendar.monthrange(year,month)days=res[1]#当前月份的天数week=res[0]+1#当前月份第一天是周几print(f========={year}年{month}月=========)print(一二三四五六日)print(=*32)#实现日历信息的输出d=1whiled=days:#循环周foriinrange(1,8):#判断是否输出ifddaysor(d==1andiweek):print(,end=)else:print({:02d}.format(d),end="")d+=1print()showdate(,12)---=========年12月=========一二三四五六日================================31

我们尝试调用了一下封装好的函数,输出年12月份日历,大家可以看看自己手机里的日历,绝对真实可靠。

好了,现在我们要完成万年历的制作了。

万年历,自然是有一个初始值,那这个初始值必须是当前时间最妥当。不然你们试试打开你们的日历,看是不是打开默认都是指向的「今天」。

那么首先,让我们获取一下当前系统的年月,这个就需要用到我们的time模块里的localtime()方法,其返回参数如下:

time.struct_time(tm_year=,tm_mon=8,tm_mday=13,tm_hour=1,tm_min=50,tm_sec=38,tm_wday=6,tm_yday=,tm_isdst=0)

那我们如何从中拿到我需要的内容?我们接着看:

importtimedd=time.localtime()year=dd.tm_yearmonth=dd.tm_monshowdate(year,month)---=========年8月=========一二三四五六日================================31

很明显,我们用year和month两个变量从得到的localtime里获取了其中的年份和月份信息。然后重新调用showdate()封装函数,将其传入。也就打印出了我们当前月份的日历。

可是这都是静态的,我们总不能就只看我们当月的月份。所以,我们接着扩展这个程序。

importtime...whileTrue:#默认输出当前年月的日历信息showdate(year,month)print(上一月下一月)c=input(请输入您的选择""or"":)#判断用户的输入内容ifc==:month-=1elifc==:month+=1else:print(您输入内容错误,请重新输入""或者""来选择。)---=========年8月=========一二三四五六日================================31上一月下一月=========年9月=========一二三四五六日================================上一月下一月

我们在程序运行中没有图形界面,无法接收鼠标信息,那就用输入和来代替一下,其逻辑是相同的。

可以看到,我们做了一个判断,当输入的时候,我月份数字减少,当我们输入的时候,月份数字增加。所以当我们输入的时候,表示下一月,数字增加,也就打印出了9月份的月份信息。

可是问题又来了,我们总不能无限加或者无限减下去吧,12月份之后不可能是13月份吧。这又该怎么办呢?

别着急,我们继续研究下该怎么改善:

importtime...whileTrue:...#判断用户的输入内容ifc==:month-=1ifmonth1:month=12year-=1elifc==:month+=1ifmonth12:month=1year+=1elifc==exit:breakelse:print(您输入内容错误,请重新输入""或者""来选择。)

既然月份是固定的数字,那就是最好办的,我们让变量控制在范围内不就好了。如果超过数字了,那就改变年份,将月份回滚为最小值或者最大值不就好了。两个简单的if解决了问题。

这就完了吗?并没有。在打印的过程当中,我发现一个问题,就是我们的月份信息不断的叠加,那导致打印区变的过长,最终都没打印完全。这并不是我们想要的,如图:

所以,其实我都还没验证到底12月份之后是否正常变为年1月了。忍不了,这个问题也必须要解决。

那如何解决呢?我想起来,在Linux命令中有一个clear命令,其功能就是将当前窗口内容清理掉。那Python中又有很多和系统操作相同的功能,这次有没有呢?就算没有,我记得os.system()似乎可以调用系统命令的。

那,我们试试看:

importoswhileTrue:os.system(clear)#默认输出当前年月的日历信息...

实际操作了一下,无法在JupyterNotebook中实现,但是当你将代码存储成.py文件之后,在shell中执行是完全可以实现的。如下图:

至此,我们本次的练习「万年历」就完成了。

大家可以下载我的源码来研究,第16课,包含一个.ipynb笔记本文件和一个.py完整文件。

有什么问题,评论区留言。

好了,下课,咱们下节课再见。




转载请注明:http://www.wannianzx.com/wnxjg/16377.html

  • 上一篇文章:
  •   
  • 下一篇文章: 没有了