企业🤖AI智能体构建引擎,智能编排和调试,一键部署,支持私有化部署方案 广告
### 4.3.2 第二层设计 接下来需要对第二层上的每个模块进行精化。 首先看 getYear 函数。这个函数的功能只是输入年份数据,可以直接用 Python 的基本 语句实现,无需分解为新的功能模块。具体代码如下: ``` def getYear(): print "This program prints the calendar of a given year." year = input("Please enter the year (after 1900): ") return year ``` 接着考虑 firstDay 函数的设计。这个函数的功能是计算 year 年 1 月 1 日是星期几,因为年历是按星期来组织每一天的显示位置的,而只要知道 1 月 1 日的显示位置,其后所有日期的显示位置也就确定了。 在 calendar 程序的规格说明中说明了,我们以 1900 年 1 月 1 日(星期一)作为基准日, 只要算出 year 年 1 月 1 日距离基准日的天数,就能知道这一天是星期几。因为从基准日开 始,过 1 天是星期二,过 2 天是星期三,…,过 6 天是星期日,过 7 天又是星期一,…。一 般地,过 n 天是星期(n+1)%7(值为 0 表示星期天)。 那么,从基准日到 year 年 1 月 1 日总共过了多少天呢?只需一点常识,就能得出下面 的公式: ``` (year – 1900) * 365 + k ``` 其中 k 是从 1900 到 year(不含)之间的闰年个数。 看上去闰年个数 k 还不清楚如何求得,我们按惯例假设一个新函数 leapyears()能够 返回所需的 k。于是可以设计 firstDay 函数如下: ``` def firstDay(year): k = leapyears(year) n = (year – 1900) * 365 + k return (n + 1) % 7 ``` 最后考虑 printCalendar 函数的设计,该函数的任务是在合适的位置按日历格式显示一年 12 个月的日历。由于问题有点复杂,我们照例进行任务分解。12 个月的日历输出显然可以用一个 for 循环来实现,循环体是显示一个月日历的代码。每个月需要先打印标题(月份和星期的名称),然后再打印日期,假设函数 heading()和 oneMonth()分别执行这两个任务,则 printCalendar 的代码如下: ``` def printCalendar(year,w): print print "=========== " + str(year) + " ==========" first = w for month in range(12): heading(month) first = oneMonth(year,month,first) ``` 函数体的第一行用于打印年份信息,接下去是打印 12 个月的日历的 for 语句。打印每个月 的日历需要知道该月 1 日是星期几。printCalendar 的参数 w 是前面算出来的 1 月 1 日 的星期信息,2 月到 12 月的 1 日则由 oneMonth 函数返回至此,我们完成了第二层设计, 可以用图 4.8 中的结构图表示到目前为止的设计结果。注意,为简明起见,图中省略了各模 块之间的界面数据。 ![](https://box.kancloud.cn/2016-02-22_56cafcdf72530.png) 图 4.8 calendar 程序的第二层结构图