1. 程式人生 > 實用技巧 >032 程式碼複用與函式遞迴

032 程式碼複用與函式遞迴

目錄

一、概述

  • 程式碼複用與模組化設計
  • 函式遞迴的理解
  • 函式遞迴的呼叫過程
  • 函式遞迴例項解析

二、程式碼複用與模組化設計

2.1 程式碼複用

把程式碼當成資源進行抽象

  • 程式碼資源化:程式程式碼是一種用來表達計算的"資源"
  • 程式碼抽象化:使用函式等方法對程式碼賦予更高級別的定義
  • 程式碼複用:同一份程式碼在需要時可以被重複使用

函式 和 物件 是程式碼複用的兩種主要形式

函式:將程式碼命名

在程式碼層面建立了初步抽象

物件:屬性和方法

<a>.<b><a>.<b>()

在函式之上再次組織進行抽象

2.2 模組化設計

分而治之

  • 通過函式或物件封裝將程式劃分為模組及模組間的表達
  • 具體包括:主程式、子程式和子程式間關係
  • 分而治之:一種分而治之、分層抽象、體系化的設計思想

緊耦合 鬆耦合

  • 緊耦合:兩個部分之間交流很多,無法獨立存在
  • 鬆耦合:兩個部分之間交流較少,可以獨立存在
  • 模組內部緊耦合、模組之間鬆耦合

三、函式遞迴的理解

3.1 遞迴的定義

函式定義中呼叫函式自身的方式

3.2 遞迴的兩個關鍵特徵

  • 鏈條:計算過程存在遞迴鏈條
  • 基例:存在一個或多個不需要再次遞迴的基例

3.3 類似數學歸納法

  • 數學歸納法
    • 證明當n取第一個值n0n0 時命題成立
    • 假設當nknk 時命題成立,證明當n=nk+1n=nk+1 時命題也成立
  • 遞迴是數學歸納法思維的程式設計體現

四、函式遞迴的呼叫過程

4.1 遞迴的實現

n!={1n(n1)!n=0otherwisen!={1n=0n(n−1)!otherwise

def
fact(n):
if n == 0: return 1 else: return n * fact(n - 1)

4.2 函式 + 分支語句

  • 遞迴本身是一個函式,需要函式定義方式描述
  • 函式內部,採用分支語句對輸入引數進行判斷
  • 基例和鏈條,分別編寫對應程式碼

4.3 遞迴的呼叫過程

五、函式遞迴例項解析

5.1 字串反轉

將字串s反轉後輸出:s[::-1]

  • 函式 + 分支結構
  • 遞迴鏈條
  • 遞迴基例
def rvs(s):
    if s == "":
        return s
    else:
        return rvs(s[1:]) + s[0]

5.2 斐波那契數列

斐波那契數列

F(n)=11F(n1)+F(n2)n=1n=1otherwiseF(n)={1n=11n=1F(n−1)+F(n−2)otherwise

F(n)=F(n1)+F(n2)F(n)=F(n−1)+F(n−2)

  • 函式 + 分支結構
  • 遞迴鏈條
  • 遞迴基例
def f(n):
    if n == 1 or n == 2:
        return 1
    else:
        return f(n - 1) + f(n - 2)

5.3 漢諾塔

  • 函式 + 分支結構
  • 遞迴鏈條
  • 遞迴基例
def hanoi(n, src, dst, mid):
    global count
    if n == 1:
        print("{}:{}->{}".format(1, src, dst))
        count += 1
    else:
        hanoi(n - 1, src, mid, dst)
        print("{}:{}->{}".format(n, src, dst))
        count += 1
        hanoi(n - 1, mid, dst, src)


count = 0
hanoi(3, 'A', 'B', 'C')
print(count)
1:A->B
2:A->C
1:B->C
3:A->B
1:C->A
2:C->B
1:A->B
7

六、單元小結

6.1 程式碼複用與函式遞迴

  • 模組化設計:鬆耦合、緊耦合
  • 函式遞迴的2個特徵:基例和鏈條
  • 函式遞迴的實現:函式 + 分支結構