1.12.定义函数

之前的过程抽象的例子调用了一个名为sqrt的Python函数,它来自math模块,用来计算平方根。一般来说,我们可以通过定义一个函数来隐藏任何计算的细节。一个函数定义需要一个名称、一组参数和一个函数体。它也可以显式地返回一个值。例如,下面定义的简单函数返回传入的值的平方。

  1. >>> def square(n):
  2. ... return n**2
  3. ...
  4. >>> square(3)
  5. 9
  6. >>> square(square(3))
  7. 81
  8. >>>

这个函数定义的语法包括名称、square和一个圆括号括起来的正式参数列表。对于这个函数,n是唯一的正式参数,这表明square只需要一段数据就可以完成它的工作。这些细节隐藏在“盒子里”,简单地计算出n**2的结果并返回它。为调用square函数,我们可以传入一个实际的参数值(在本例中为3)来让Python计算他。请注意,对square的调用会返回一个整数,该整数又可以被传递给另一个调用。

我们可以使用一种叫做“牛顿法”的著名技术来实现我们自己的平方根函数。牛顿法用近似平方根来的执行迭代运算,该计算收敛于正确的值。等式newguess = 1/2 *(oldguess + n/oldguess)取n值,并通过在随后的迭代中使每个newguess成为oldguess来反复猜测平方根。这里最初始的猜测是n/2。 Listing 1显示了一个接受值n的函数定义,并在进行20次猜测后返回n的平方根。同样,牛顿法的细节隐藏在函数定义中,用户不需要知道任何关于实现的内容,就可以使用这个函数来实现它的预期目的。 Listing 1还显示了使用#字符作为注释标记。此行#后面的任何字符都将被忽略。

Listing 1

  1. def squareroot(n):
  2. root = n/2 #initial guess will be 1/2 of n
  3. for k in range(20):
  4. root = (1/2)*(root + (n / root))
  5. return root
  1. >>>squareroot(9)
  2. 3.0
  3. >>>squareroot(4563)
  4. 67.549981495186216
  5. >>>

自我检测

这是一个真正涵盖到目前为止所有内容的自我检查。 你可能听说过无限猴子定理? 该定理指出,猴子在打字机键盘上随机敲击键无限时间几乎肯定会输入一个给定的文本,例如威廉·莎士比亚的全集。好吧,假设我们用Python函数替换猴子。 你认为Python函数生成莎士比亚的一个句子需要多长时间? 我们要的目标句是:“我觉得它就像一只黄鼠狼”

您别想在浏览器中运行这个,所以请启动您最喜欢的Python IDE。我们模拟这个的方法是写一个函数,通过从字母表中26个字母和空格中随机选择字母来生成一个27个字符长的字符串。我们将编写另一个函数,通过将随机生成的字符串与目标进行比较,从而为每个生成的字符串打分。

第三个函数会反复调用生成函数和打分函数,如果百分之百的字母是正确的,我们就完成了。如果字母不正确,我们就会生成一个全新的字符串。为了更方便地跟踪程序的进度,第三个函数应该打印出目前为止生成的最佳字符串及其每1000次尝试的分数。

自我挑战

看看你是否可以通过保持正确的字母来改进程序,并且只修改目前最好的字符串中的一个字符。这是“爬坡”算法中的一种算法,如果它比前一个更好,我们只保留结果。