基于股票大数据分析的Python入门实战(视频教学版)
上QQ阅读APP看书,第一时间看更新

1.4 通过范例程序加深对Python语法的认识

在本节中,我们将综合运用之前学到的函数、条件分支语句和循环语句来实现若干范例程序。在编写、调试、执行范例程序的过程中,也需要调试(Debug)代码中的问题,本节也会介绍调试代码的相关技巧。

1.4.1 实现冒泡排序算法

冒泡排序算法的执行步骤是,每次比较两个相邻的元素,如果它们次序有误,则交换位置。基于Python语言实现的冒泡排序范例程序如下:

1    # !/usr/bin/env python
2    # coding=utf-8
3    
4    # 定义冒泡排序的函数
5    def SortFunc(numArray):
6        loopTimes=0; # 记录循环冒泡比较的次数
7        while loopTimes< len(numArray)-1:
8            # index为待比较元素的下标
9            for index in range(len(numArray)-loopTimes-1):
10                if numArray[index] > numArray[index+1]:
11                    tmp=numArray[index]
12                    numArray[index]=numArray[index+1]
13                    numArray[index+1]=tmp
14            loopTimes=loopTimes+1
15        return numArray
16    
17    unSortedNums=[10,12,48,7,5,3]
18    print(SortFunc(unSortedNums))

从第5行到第15的程序代码中,使用def定义了实现冒泡算法的SortFunc函数,在其中是通过两层循环来实现排序过程中的交换操作。

在第7行的while循环条件中设置了循环比较的次数,由于是待比较元素之间的比较,因此循环次数是待比较列表的长度减1。在第10行对比了相邻的两个元素,如果与目标的顺序不一致,则通过第11行到第13行的代码交换两个元素的位置。

在第17行中,定义了一个未经排序的列表,在第18行中调用了SortFunc函数,并在这行中通过print语句输出了排序后的结果。

1.4.2 计算指定范围内的质数

质数是只能被1和自身整除的自然数,在如下的PythonCalPrime.py范例程序中,将使用两层嵌套的for循环来寻找并打印指定范围内的质数。

1    # !/usr/bin/env python
2    # coding=utf-8
3    # 打印质数的方法
4    def printPrime(maxNum):
5        num=[];
6        currentNum=2
7        for currentNum in range(2,maxNum+1):
8           devidedNum=2
9           for devidedNum in range(2,currentNum+1):
10              if(currentNum%devidedNum==0):
11                  break
12           if currentNum == devidedNum:
13               num.append(currentNum) # 把质数加入到列表里
14           #print(num)
15        print(num)
16    
17    printPrime(101)

在第4行的printPrime方法(或称为函数)的定义中,通过参数maxNum来指定待打印质数的上限。在第7行的外层for循环中,通过调用range方法,依次遍历2到 maxNum范围内的自然数,这里请注意,如果把外层条件写成“for currentNum in range(2,maxNum+):”,则无法遍历maxNum这个数。

在执行外层循环时,第9行的内层for循环会依次让currentNum除以从2到该数本身的各个自然数,请注意,这里第9行的写法依然是需要加1,即“range(2, currentNum+1)”。

在执行内层循环时,如果通过第10行的判断,发现从1到该数本身之外还存在其他被整除的因数,则说明该数不是质数,那么就执行第11行的break语句退出内层for循环。如果内层循环完成后,且满足第12行的if条件,则说明这个数只有1和本身的因数,于是执行第13行的语句把该数加入到num列表中(num就是存储已找到质数的列表)。

第17行调用printPrime函数,执行的结果就能打印出101(含101)内所有的质数。这里请注意,由于Python是通过缩进来判断程序语句块的层次,如果用错了缩进格式,比如把第15行的程序代码再缩进了4个空格(如第14行那样,即和第14行语句起始对齐),那么就会在每次外层循环的最后都打印出num中的内容,其实就是把执行的中间结果打印出来了。

1.4.3 通过Debug调试代码中的问题

在编写代码时,一旦出现了问题,就需要通过Debug方法来调试、排错和修改有问题的程序语句。

以1.4.2小节的PythonCalPrime.py范例程序为例,如果我们错误地把第9行的代码写成如下的样子,即在range中,没有对currentNum加1。

    for devidedNum in range(2,currentNum):

这时输出的结果只有2,明显和我们预期的不一致,此时,就可以通过如下的步骤来排查程序中的问题。

步骤1 在代码的左边,用鼠标双击加入断点,如图1-10所示。该程序用了两层嵌套for循环,为了调试方便,可以把断点设置在外层for语句代码的位置。

图1-10 调试时在程序代码里加入断点

步骤2 在代码的空白位置,单击鼠标右键,在弹出的快捷菜单中,依次单击“Debug As”→“Python Run”,以Debug的方式运行程序,如图1-11所示。

图1-11 以Debug的方式运行程序

步骤3 以Debug方式启动程序的运行后,光标会停在之前设置的断点位置,如果此时单击“Step Over”按钮(快捷键为【F6】),光标则会依次跳到下一条语句上,如果此时把鼠标移动到currentNum等变量上,就能看到这个变量当前的值,如图1-12所示。

图1-12 调试程序时查看变量当前值的效果图

当currentNum是3的时候,我们编写这句程序语句的本意是让devidedNum依次遍历2和3这两个数,这样在退出内层for循环,执行if语句时,currentNum等于devidedNum,结果就能判定3是质数。

但是,通过“单步执行”调试时,我们看到此时当devidedNum取值为3时,并没有执行内层循环的“if(currentNum%devidedNum==0):”语句,而是直接退出了内层循环,由此我们就发现了问题,原来是设置内层for循环条件时,range变量的第二个参数设置得不对。于是改成如下的“currentNum+1”后再运行,结果就正确了。

    for devidedNum in range(2,currentNum+1)

在开发Python应用程序时,读者或许用的是其他的开发环境。虽然在不同的开发环境中,代码调试的具体步骤可能不同,但通过代码调试排查问题的思路都是通用的。一般来说,通过如下三个调试的步骤,能发现程序中的绝大多数问题。

步骤1 在合适的位置加上断点,如果不知道问题所在,就从程序的开始位置加上断点,待确认问题范围后再不断地添加或去掉断点。

步骤2 可以通过单步执行,查看具体场景里每个变量的值,也可以通过不断地“单步执行”,观察程序运行的顺序是否和我们预期的一样。

步骤3 还可以通过“Step Into”的方式,进入到具体函数内部排查问题,如图1-13所示,把断点设置在printPrime函数上,以Debug方式启动程序后,再单击“Step Into”菜单选项,就会进入到这个函数的第1行,如图1-14所示。

图1-13 在函数上加断点

图1-14 通过Step Into进入函数内部调试