目录

  • 1 安装Python环境
    • 1.1 Python开发环境安装
    • 1.2 开始了解一些语句编写小程序
    • 1.3 尝试更多的小程序
    • 1.4 试一试:开始自己编写程序(可选)
  • 2 变量与字符串
    • 2.1 变量
    • 2.2 输出
    • 2.3 字符串
    • 2.4 字符串常用方法
    • 2.5 案例一温度转换
    • 2.6 案例二turtle库
      • 2.6.1 turtle库基础知识
    • 2.7 实践与练习
  • 3 最基本的魔法函数
    • 3.1 重新认识函数
    • 3.2 开始创建函数
    • 3.3 练习题
    • 3.4 传递参数与参数类型
    • 3.5 案例:文本敏感词过滤器
  • 4 循环与判断
    • 4.1 程序的三种控制结构
    • 4.2 逻辑控制
      • 4.2.1 比较运算
      • 4.2.2 成员运算符与身份运算符
      • 4.2.3 布尔运算符
    • 4.3 条件控制
    • 4.4 循环
      • 4.4.1 for 循环
      • 4.4.2 while 循环
      • 4.4.3 练习题
    • 4.5 综合练习:制作小游戏
      • 4.5.1 设计思路
      • 4.5.2 编程实现
      • 4.5.3 练习题
    • 4.6 PS:程序的异常处理
  • 5 数据结构
    • 5.1 数据结构
    • 5.2 列表
    • 5.3 字典
    • 5.4 元组
    • 5.5 集合
    • 5.6 数据结构的一些技巧
    • 5.7 综合项目:词频统计
  • 6 文件和数据格式化
    • 6.1 文件的使用
    • 6.2 PIL库的使用--操作图像文件
    • 6.3 数据的格式化和处理
      • 6.3.1 一维数据的格式化和处理
      • 6.3.2 二维数据的格式化和处理
    • 6.4 实例:CSV格式的HTML展示
    • 6.5 高维数据的格式化和处理
      • 6.5.1 高维数据的格式化和处理
      • 6.5.2 json库的使用
    • 6.6 项目1制作英语学习词典
  • 7 开始使用第三方库
    • 7.1 令人惊叹的第三方库
    • 7.2 安装第三方库
      • 7.2.1 第三方库的安装
      • 7.2.2 实例:pip安装脚本
    • 7.3 使用第三方库
      • 7.3.1 实例:文本词频统计
      • 7.3.2 案例:中文分词与词云统计
      • 7.3.3 案例:数据分析与可视化
  • 8 程序设计方法学
    • 8.1 自顶向下设计和自底向上执行测试
    • 8.2 pyinstaller库的使用--打包源文件
  • 9 2020校通识课程结业
  • 10 运算符、基本数据类型
    • 10.1 数值类型及其操作
    • 10.2 math库函数
    • 10.3 案例学习:天天向上的力量
    • 10.4 第四周作业
    • 10.5 字符串类型及其操作
    • 10.6 案例学习:文本进度条
  • 11 Python综合设计实验一
    • 11.1 Python基本操作
    • 11.2 课堂实战练习
  • 12 程序控制结构
    • 12.1 分支结构(选择结构)
    • 12.2 循环结构
    • 12.3 程序的异常处理
    • 12.4 random库的使用
  • 13 函数和代码复用
    • 13.1 函数的定义与调用
    • 13.2 函数参数传递
    • 13.3 模块化编程-通过函数复用
    • 13.4 datetime库的使用
    • 13.5 案例:七段数码管绘制
    • 13.6 函数的递归
    • 13.7 案例:科赫曲线(雪花)的绘制
  • 14 组合数据类型
    • 14.1 组合数据类型概述
    • 14.2 列表类型与操作
    • 14.3 实例:基本统计值计算
    • 14.4 字典类型和操作
    • 14.5 实例:Python之禅
  • 15 类和可口可乐
    • 15.1 定义类
    • 15.2 类的实例化
    • 15.3 类属性引用
    • 15.4 实例属性
    • 15.5 实例方法
    • 15.6 魔术方法
    • 15.7 类的继承
    • 15.8 类的扩展理解
    • 15.9 类的实践
  • 16 网络爬虫方向和自动化
    • 16.1 网络爬虫
    • 16.2 玫瑰花的绘制
  • 17 课程项目设计与实现
    • 17.1 下载项目文档
    • 17.2 参考案例学习
    • 17.3 项目实现步骤
    • 17.4 学习资源
自顶向下设计和自底向上执行测试
  • 1 自顶向下设计
  • 2 自底向上执行测试

自顶向下设计

本小节以模拟体育竞技进行竞技分析的实例,通过本实例了解程序设计中的“自顶向下,自底向上”的程序设计思想。

从各种球类比赛规则中抽象出这样的一种体育竞技规则

(1)两个球员在一个有4而边界的场地上用球拍击球。

(2)开始比赛时,其中一个球员首先发球。然后,球员交替击球,直到可以判定得分为止,此过程称为回合。当一名球员未能进行一次合法击球时,回合结束。未能打中球的球员输掉这个回合。如果输掉这个回合的是发球方,那么发球权交给另一方; 如果输掉的是接球方,则仍然由这个回合的发球方继续发球。总之,每回合结束,由赢得该回合的一方发球。

(3)球员只能在其发球局中得分。

(4)先达到15分的球员赢得一该局的比赛。


计算机在模拟此竞技中,运动员的能力级别将通过发球发赢得本回合的概率来表示。例如,能力值0.6表示该球员在其发球局有60%的可能性赢得1分。程序首先接收两个球员的能力值,然后利用这个值采用概率方法模拟多场比赛。程序最后输出比赛运行结果。

用IPO来描述程序的模拟问题:

输入:球员A和球员B的能力值,模拟比赛的次数

处理:模拟比赛过程

输出:球员A和B分别赢得球赛的概率。

抽象这个问题时,将球员失误、犯规等可能性一并考虑在能力值中,在每局比赛中,球员A先发球。可以期望输出结果如下:

    模拟比赛总次数:400

   球员A获胜次数:201(50.2%)

   球员B获胜次数:199(49.8%)


接下来,我们从自顶向下设计该程序。

自顶向下设计的基本思想是以一个总问题开始,试图把它表达为很多小问题组成的解决方案。再用同样的技术依次解决小问题,最终问题变得非常小,以至于可以很容易解决。然后只需把所有的碎片组合起来,就组成解决总问题的程序。

  1. 顶层设计:最重要部分

    依据以上IPO描述,将模拟问题化解为以下4个基本设计步骤:

       step1:打印程序的介绍信息。

      step2:获得程序运行所需的参数:球员A能力值,球员B能力值,模拟次数: probA,probB,n

      step3:依据probA,probB,模拟n 次比赛

      step4: 输出球员A和球员B获胜场次及获胜率

      依据将基础设计,作为开始进行自顶向下设计的顶层设计。顶层设计不写出具体的代码,仅给出函数定义,将这些函数放入main()函数中。

  •      step1是为提高用户体验,打印一些必要的说明信息。定义这个功能名printIntro()

          def main()

                 printIntro()

  •     step2获得用户输入,得到probA,probB,n 。 定义这个功能名为getInputs()

          def main()

                printIntro()

                probA,probB,n= getInputs()

  •    step3用probA,probB,模拟n次比赛。定义名为simNGames()函数,返回结果为球员A赢次数和B赢的次数:winsA, winsB。          

          def main()

                   printIntro()

                    probA,probB,n= getInputs()

                    winsA, winsB=simNGames(n, probA,probB)

  • step4输出结果。定义名为printSummary()函数完成。

         def main()

                   printIntro()

                    probA,probB,n= getInputs()

                    winsA, winsB=simNGames(n, probA,probB)

                    printSummary(winsA, winsB)

2.第二层设计

经过顶层设计,main()成为顶得结构,其程序结构图如下:

                                                           图1 体育竞技分析程序结构图:顶层设计

自顶向下设计的第二阶段是实现或进一步抽象第2层函数。

  •  printIntro()仅是输出程序的介绍,用print()表达。

def printIntro():

    print("模拟两选手A和B的比赛")

    print("程序运行需要A和B的能力值[0..1]")

  • getInputs()函数提示用户输入3个值,代码也可直接表达:

def getInputs():

    a=eval(input("输入A的能力值:"))

    b=eval(input("输入B的能力值:"))

    n=eval(input("输入模拟的场次:"))

    return a,b,n

  • simNGames()函数是整个程序的核心,模拟n场比赛,并记录球员的赢的次数。重复n次,每次记录赢的情况,用计数器变量完成。代码:

def simNGames(n,proA,proB):

    winsA,winsB=0,0

    for i in range(n):

        scoreA,scoreB=simOneGame(proA,proB)

        if scoreA > scoreB:

            winsA+=1

        else:

            winsB+=1

    return winsA,winsB

代码中设计了simOneGame()函数,用于模拟一场比赛,这个函数需要知道球员的能力值,返回球员的得分,以下图给出了这个设计的整体结构图更新:

                                                图2  体育竞技分析程序结构图:第二阶段


3.第三层设计

第三层设计,需要实现simOneGame()函数。为模拟一场比赛,需要根据比赛规则来编写代码,两球员持续对攻直到比赛结束。可以用循环结构,判断条件是比赛结束。同时还要记录比赛的得分,保留发球局标记,总之,尽可能详细模拟比赛过程。那如何判断发球方的得分呢?可以考虑用随机数与能力值对比来模拟。如果球员A拥有发球权,其概率值大于随机值,表明其得分,否则发球权交给球员B,同样情形适合于B。代码如下:

def simOneGame(proA,proB):

    scoreA,scoreB=0,0

    serving = "A"

    while not gameOver(scoreA,scoreB):

        if serving == "A":

            if random()<proA:

                scoreA +=1

            else:

                serving="B"

        else:

            if random()<proB:

                scoreB +=1

            else:

                serving="A"

    return scoreA,scoreB

 这里进一步设计了gameOver()函数,用来表示一场比赛结束的条件,对于不同比赛结束条件可能不同,单独将其封装为函数有助于简化根据不同规则修改函数的代价,提高代码可维护性。gameOver()返回值True或False。

                                                 图3 体育竞技分析程序结构图:第三阶段

若比赛规则为,当任意一球员分数达到15分时比赛结束。那gameOver()函数实现代码如下:

def gameOver(scoreA,scoreB):

    return scoreA==15 or scoreB==15

最后,第二层的printSummary()函数,代码如下:

def printSummary(winsA,winsB):

    n= winsA +winsB

    print("比赛开始,现模拟{}场比赛。".format(n))

    print("A选手赢了{}场比赛,占{:.1%}。".format(winsA,winsA/n))

    print("B选手赢了{}场比赛,占{:.1%}。".format(winsB,winsB/n))

将上述代码放在一起,就形成了解决整个问题的代码simulateGame.py。

代码可从平台“资料”中“实例代码”中下载。

4.自顶向下设计过程总结

从问题输入输出确定开始,整体设计逐渐向下进行。每一层以大体算法描述开始,然后逐步细化成代码,细节被函数封装,整个过程可以概括为以下4个步骤。

(1)将算法表达为一系列小问题

(2)为每个小问题设计接口

(3)通过将算法表达为接口关联的多个小问题来细化算法

(4)为每个小问题重复上述过程

自顶向下设计是一种开发复杂程序最具价值的设计理念和工具,设计过程自然且简单,自顶向下设计通过封装实现抽象,利用了模块化设计的思想。