4.2.2 用函数改善程序结构

上一节讨论了函数的减少重复代码、精简程序的作用,并利用函数的这个功能将程序 4.1 改进成了程序 4.2。在该节的最后,我们也给出了一个不宜用函数来减少重复代码的情况。

还能不能利用函数将程序 4.2 变得更好呢?

我们在 4.1 节中一般地讨论了模块化编程,在 Python 中,函数就是用于模块化编程的 重要工具。当算法很复杂时,程序就会变得难以理解。据说人类擅长同时应付 8 到 10 件事 情,当面对成百上千行的算法时,最好的程序员也会感到难以把握。应对程序复杂性的一种 方法就是模块化,将程序分解成多个较小的相对独立的子程序。下面我们来看程序 4.2 还能 怎样改进。

我们定义一个新函数 treetrunk,它的语句序列就是程序 4.2 的主函数中用于画树干的三条 print 语句。即:

def treetrunk(): 
    print "   #"
    print "   #"
    print "   #"

然后我们用这个函数取代主函数的那三条 print 语句,就得到画树程序的一个新版本。

【程序 4.3】tree3.py

def treetop(): 
    print "   *" 
    print "  ***" 
    print " *****" 
    print "*******"
def treetrunk(): 
    print "   #"
    print "   #"
    print "   #"
def main():
    treetop() 
    treetop() 
    treetrunk()
main()

注意我们将程序主函数的名字从 tree 改成了更符合惯例的 main。

简单地比较一下程序 4.2 与 4.3 这两个版本就看出,由于多了函数 treetrunk 的定义与调用,新版本的代码不但没有减少,反而增加了。那为何要引进 treetrunk 函数呢?其实我们的目的是使主程序的结构更清晰,从而更容易理解程序功能。通过将一些实现细节转移到一个单独的函数中,并对函数进行合适的命名,能够使程序的可读性大大增强。例如我 们来读程序 4.3 的主程序 main,就会发现该程序不过是先画树冠(由两个相同形状组成), 再画树干而已,程序的功能一目了然。

如果进一步发挥上述思想,就会发现程序 4.3 的结构还不够完美。问题出在主程序的第 一步——画树冠,这一项任务逻辑上是个整体却用了两个函数调用来完成,这就好比老师对 学生说“请大家画上一半树冠,再画下一半树冠”,显然不如直接说“请大家画树冠”来得 清晰易懂。因此,我们再引入一个新函数用于隐藏树冠的实现细节(上下两部分),从而得 到程序 4.4,这个版本在避免重复代码和模块化两方面可以说达到了完美。

【程序 4.4】tree4.py

def treetop1(): 
    print "   *" 
    print "  ***" 
    print " *****" 
    print "*******"
def treetop():
    treetop1() 
    treetop1()
def treetrunk(): 
    print "   #"
    print "   #"
    print "   #"
def main():
    treetop() 
    treetrunk()
main()

现在再来读主程序 main,显然更容易理解了——从程序顶层看,整个程序不外乎就是画树 冠、画树干两步而已。如果只想了解程序的总体功能,那么读懂 main 函数就够了;如果还 想了解更多细节,那就再去读辅助函数 treetop1 和 treetrunk 等。

读者在编程时应当多模仿、多体会程序 4.4 中函数的用法,并学会欣赏模块化程序在结 构方面的优美。