使用 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