4.2.3 用函数增强程序的通用性

我们说过,程序 4.4 在减少重复代码和模块化两方面已经做得很好,但这并不意味着该 程序在各方面都已经完美。例如,如果我们希望换用字符”^”再画一棵树,以便比较哪个更 好看些,该如何做呢?显见的做法是仿照用”*“画树的代码重写画树冠的函数,而树干部分 可以重用。于是得到下面的代码:

【程序 4.5】tree5.py

  1. def treetop1():
  2. print " *"
  3. print " ***"
  4. print " *****"
  5. print "*******"
  6. def treetop2():
  7. print " ^"
  8. print " ^^^"
  9. print " ^^^^^"
  10. print "^^^^^^^"
  11. def star_treetop():
  12. treetop1()
  13. treetop1()
  14. def caret_treetop():
  15. treetop2()
  16. treetop2()
  17. def treetrunk():
  18. print " #"
  19. print " #"
  20. print " #"
  21. def main():
  22. star_treetop()
  23. treetrunk()
  24. print
  25. caret_treetop()
  26. treetrunk()
  27. main()

此版本的执行结果如下:

  1. *
  2. ***
  3. *****
  4. *******
  5. *
  6. ***
  7. *****
  8. *******
  9. #
  10. #
  11. #
  12. ^
  13. ^^^
  14. ^^^^^
  15. ^^^^^^^
  16. ^
  17. ^^^
  18. ^^^^^
  19. ^^^^^^^
  20. #
  21. #
  22. #

虽然程序 4.5 满足了功能需求,但是从程序设计角度说是很笨拙的,因为这是一种“头 痛医头脚痛医脚”的方法,即为每一种特殊情形创建新的代码。更好的做法是用一个一般的 函数来处理所有特殊情形。鉴于 treetop1 和 treetop2 的非常类似,我们可以从他们抽 象出一个通用的画树冠的函数,使得该函数能够取代 treetop1 和 treetop2。

函数的通用性可以通过引入参数(parameter)来实现。要理解参数的作用,可以简单地与数学函数的自变量进行类比。以函数 f(x) = x2 为例,对于给定的自变量值 10,函数计算 出函数值 f(10) = 100;换不同的自变量值 20,则函数又计算出另一个函数值 f(20) = 400。编 程语言中的函数参数具有类似的行为,输入不同的参数值,则函数执行后可产生不同的结果。

下面我们设计一个通用的画树冠的函数 treetop(ch),其中参数 ch 表示用来作画的 字符。为了控制树的形状,函数定义中使用了字符串格式化运算。

  1. >>> def treetop(ch):
  2. print " %s" % (ch)
  3. print " %s" % (3 * ch)
  4. print " %s" % (5 * ch)
  5. print "%s" % (7 * ch)

在交互环境定义了函数 treetop(ch)后,我们接着来测试它的效果。下面是测试例子:

  1. >>> treetop('*')
  2. *
  3. ***
  4. *****
  5. *******
  6. >>> treetop('^')
  7. ^
  8. ^^^
  9. ^^^^^
  10. ^^^^^^^
  11. >>> treetop('A')
  12. A
  13. AAA
  14. AAAAA
  15. AAAAAAA

可见函数 treetop(ch)确实具有通用性,只要为它的参数提供一个字符值,就能用该字符 画出树冠形状。下面我们利用 treetop(ch)函数来改写程序 4.5:

【程序 4.6】tree6.py

  1. def treetop(ch):
  2. print " %s" % (ch)
  3. print " %s" % (3 * ch)
  4. print " %s" % (5 * ch)
  5. print "%s" % (7 * ch)
  6. def star_treetop():
  7. treetop("*")
  8. treetop("*")
  9. def caret_treetop():
  10. treetop("^")
  11. treetop("^")
  12. def treetrunk():
  13. print " #"
  14. print " #"
  15. print " #"
  16. def main():
  17. star_treetop()
  18. treetrunk()
  19. print
  20. caret_treetop()
  21. treetrunk()
  22. main()

此版本的执行结果和程序 4.5 完全一样,但是比较两者的代码会发现,程序 4.6 将程序 4.5

中的两个函数合二为一,增强了通用性。以后如果想换用其他字符画树,修改程序 4.6 比修

改程序 4.5 要简单得多。