使用 Linkbot 学习 Python 3 / 高级函数示例
外观
有些人觉得这一部分很有用,有些人觉得它很混乱。如果你觉得它很混乱,你可以跳过它。现在我们将对以下程序进行逐步讲解
def mult(a, b):
if b == 0:
return 0
rest = mult(a, b - 1)
value = a + rest
return value
print("3 * 2 = ", mult(3, 2))
基本上,该程序创建一个正整数乘法函数(比内置的乘法函数慢得多),然后使用该函数来演示该函数。该程序演示了递归的使用,递归是迭代(重复)的一种形式,其中一个函数反复调用自身,直到满足退出条件。它使用重复加法来得到与乘法相同的結果:例如 3 + 3(加法)与 3 * 2(乘法)的结果相同。
- 问题:程序的第一件事是什么?
- 答案:首先是使用以下代码行定义函数 mult
def mult(a, b):
if b == 0:
return 0
rest = mult(a, b - 1)
value = a + rest
return value
- 这创建了一个函数,该函数接受两个参数,并在完成后返回一个值。稍后可以运行此函数。
- 接下来会发生什么?
- 函数之后的下一行,
print("3 * 2 = ", mult(3, 2))
运行。 - 它做了什么?
- 它打印出
3 * 2 =
和mult(3, 2)
的返回值。 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。由于这些是本地值,因此它们不会影响a
和b
的先前值。 - 然后呢?
- 由于
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 = 3
,rest = 0
,因此现在value = 3
。 - 接下来会发生什么?
- 运行
return value
这行代码。这从函数中返回 3。这也退出mult(3, 1)
函数的运行。在调用return
之后,我们返回到运行mult(3, 2)
。 - 我们在
mult(3, 2)
中的哪里? - 我们有变量
a = 3
和b = 2
,并且正在检查rest = mult(a, b - 1)
这行代码。 - 那么现在会发生什么?
- 变量
rest
被分配了值 3。下一行代码value = a + rest
将value
设置为3 + 3
或 6。 - 那么现在会发生什么?
- 运行下一行代码,这从函数中返回 6。现在我们回到了运行
print("3 * 2 = ", mult(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
。
这就是整个过程的工作原理
3 * 2 3 + 3 * 1 3 + 3 + 3 * 0 3 + 3 + 0 3 + 3 6
通过解决同一问题的较小版本来解决问题的编程结构称为递归。在本章的示例中,递归是通过定义一个函数调用自身来实现的。这有助于实现对编程任务的解决方案,因为它可能足以考虑问题的下一步,而不是一次考虑整个问题。它也很有用,因为它允许使用简单易读的代码表达一些数学概念。
任何可以使用递归解决的问题都可以使用循环重新实现。使用循环通常会导致更好的性能。但是,使用循环的等效实现通常更难正确完成。
递归 的最直观的定义可能是
- 递归
- 如果你仍然不明白,请参见递归。
如果你觉得乘法示例没有意义,请尝试逐步讲解阶乘示例。
factorial.py
#defines a function that calculates the factorial
def factorial(n):
if n <= 1:
return 1
return n * factorial(n - 1)
print("2! =", factorial(2))
print("3! =", factorial(3))
print("4! =", factorial(4))
print("5! =", factorial(5))
输出
2! = 2 3! = 6 4! = 24 5! = 120
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