跳转到内容

Python 3 非程序员教程/高级函数示例

来自维基教科书,开放世界开放书籍

注意:有些人发现这一节很有用,有些人则觉得它很混乱。如果你觉得它很混乱,可以跳过它,继续下一节。

为了展示更高级的函数使用方式,我们现在将对以下程序进行逐步讲解

def mult(a, b):
    if b == 0:
        return 0
    rest = mult(a, b - 1)
    value = a + rest
    return value
result = mult(3, 2)
print("3 * 2 = ", result)

基本上,这个程序创建了一个正整数乘法函数(比内置乘法函数慢得多),然后用一个函数的使用来演示这个函数。这个程序演示了递归的使用,递归是迭代(重复)的一种形式,其中有一个函数重复调用自身,直到满足退出条件。它使用重复加法来获得与乘法相同的結果:例如,3 + 3(加法)与 3 * 2(乘法)的结果相同。

问题:程序首先做什么?
答案:首先是使用以下几行定义了函数 mult
def mult(a, b):
    if b == 0:
        return 0
    rest = mult(a, b - 1)
    value = a + rest
    return value
这将创建一个函数,该函数接受两个参数,并在完成时返回一个值。稍后可以运行此函数。
接下来会发生什么?
函数后面的那行,result = mult(3, 2) 会被运行。
这一行做了什么?
这一行将把 mult(3, 2) 的返回值赋给变量 result
那么 mult(3, 2) 返回什么呢?
我们需要对 mult 函数进行逐步讲解才能找出答案。
接下来会发生什么?
变量 a 被分配了值 3,变量 b 被分配了值 2。
然后呢?
运行 if b == 0: 这行。由于 b 的值为 2,所以这行是假的,因此跳过 return 0 这行。
然后呢?
运行 rest = mult(a, b - 1) 这行。这一行将局部变量 rest 设置为 mult(a, b - 1) 的值。 a 的值为 3, b 的值为 2,所以函数调用是 mult(3,1)
那么 mult(3, 1) 的值是多少呢?
我们需要使用参数 3 和 1 来运行 mult 函数。
所以接下来会发生什么?
函数运行中,局部变量被设置为 a 的值为 3, b 的值为 1。由于这些是局部值,所以它们不会影响 ab 的先前值。
然后呢?
由于 b 的值为 1,所以 if 语句为假,所以下一行变为 rest = mult(a, b - 1)
这一行做了什么?
这一行将 mult(3, 0) 的值分配给 rest。
那么那个值是什么呢?
我们必须再运行一次函数才能找出答案。这次 a 的值为 3,b 的值为 0。
所以接下来会发生什么?
函数中要运行的第一行是 if b == 0: b 的值为 0,所以要运行的下一行是 return 0
return 0 这行做了什么?
这一行将值 0 返回函数。
所以呢?
所以现在我们知道 mult(3, 0) 的值为 0。现在我们知道 rest = mult(a, b - 1) 这一行做了什么,因为我们已经使用参数 3 和 0 运行了 mult 函数。我们已经完成了 mult(3, 0) 的运行,现在回到了运行 mult(3, 1)。变量 rest 被分配了值 0。
接下来运行哪一行?
接下来运行 value = a + rest 这一行。在此函数运行中,a = 3rest = 0,所以现在 value = 3
接下来会发生什么?
运行 return value 这一行。这将从函数中返回 3。这还将退出 mult(3, 1) 函数的运行。在调用 return 之后,我们返回运行 mult(3, 2)
我们在 mult(3, 2) 中在哪里?
我们有变量 a = 3b = 2,并且正在检查 rest = mult(a, b - 1) 这一行。
所以现在会发生什么?
变量 rest 被分配了 3。下一行 value = a + restvalue 设置为 3 + 3 或 6。
所以现在会发生什么?
运行下一行,这将从函数中返回 6。我们现在回到了运行 result = mult(3, 2) 这一行,现在可以将值 6 分配给变量 result
接下来会发生什么?
函数后面的那行,print("3 * 2 = ", result) 会被运行。
这做了什么?
它打印 3 * 2 = result 的值,即 6。打印的完整行是 3 * 2 = 6
总的来说发生了什么?
基本上我们使用两个事实来计算这两个数字的倍数。第一个是任何数字乘以 0 等于 0(x * 0 = 0)。第二个是,一个数字乘以另一个数字等于第一个数字加上第一个数字乘以第二个数字减 1(x * y = x + x * (y - 1))。所以发生的是,3 * 2 首先被转换为 3 + 3 * 1。然后 3 * 1 被转换为 3 + 3 * 0。然后我们知道任何数字乘以 0 等于 0,所以 3 * 0 等于 0。然后我们可以计算出 3 + 3 * 0 等于 3 + 0,即 3。现在我们知道 3 * 1 等于多少,所以我们可以计算出 3 + 3 * 1 等于 3 + 3,即 6

这就是整个过程的工作原理

mult(3, 2)
3 + mult(3, 1)
3 + 3 + mult(3, 0)
3 + 3 + 0
3 + 3
6

通过解决问题的较小版本来解决问题的编程结构称为递归。在本节的示例中,递归是通过定义一个函数来实现的,该函数调用自身。这有利于实现编程任务的解决方案,因为它可能只需要考虑问题的下一步,而不是同时考虑整个问题。它也很有用,因为它允许用简洁易懂的代码来表达一些数学概念。

任何可以用递归解决的问题都可以用循环重新实现。使用后者通常会带来更好的性能。然而,使用循环的等效实现通常更难正确完成。

递归 的最直观的定义可能是

递归
如果你仍然不明白,请参阅递归

如果乘法示例没有讲清楚,请尝试逐步讲解阶乘示例。

factorial.py

#defines a function that calculates the factorial

def factorial(n):
    if n == 0:
        return 1
    if n<0:
        return "Error, negative numbers do not have factorial values!!"
    return n * factorial(n - 1)

print("2! =", factorial(2))
print("3! =", factorial(3))
print("4! =", factorial(4))
print("5! =", factorial(5))
print("-3! =", factorial(-3))

输出

2! = 2
3! = 6
4! = 24
5! = 120
-3! = Error, negative values do not have factorial values!!

countdown.py

def count_down(n):
    print(n)
    if n > 0:
        return count_down(n-1)

count_down(5)

输出

5
4
3
2
1
0


Python 3 非程序员教程
 ← 定义函数 高级函数示例 列表 → 
华夏公益教科书