Python程式設計

Lesson 8: 函式與遞迴

Last updated: 2024/10/8

Outline

  • 自訂函式
  • 內建函式

函式Function

Function

發音: Func-shun

函式: 一段常需重複使用的程式碼

Parameter

發音: Pa-rame-ter

參數: 特殊變數,用來傳遞資料進函式

def Hello():         # 定義函式
    print('Hello')   # 函式主體

Hello()    # 呼叫函式Hello
Hello()    # 可多次呼叫
def Km2Mile(distance):    # 需要參數之函式
    mile = distance/1.609
    return mile           # 函式回傳值

speed = Km2Mile(150)      # 呼叫函式
print('%6.1f' % speed)

函式定義好之後,不會直接執行,可重複呼叫使用

函式可接受參數、回傳計算值

函式自訂函式(1/9)

def 函式名稱(參數1, 參數2...):
    程式區塊   # 函式主體
    return 回傳值1, 回傳值2...
def do_nothing():
    pass	# 不做任何事
    
# 主程式
do_nothing()    # 呼叫函式

參數1, 參數2...可省略,()不可省略

視需要return回傳值,如不回傳return可省略

函式Function

  • 獨立小單元,可重複呼叫
  • 以def定義之
  • 必須由其他程式碼呼叫

範例

基本觀念

def do_nothing():
    pass    # 不做任何事

def print_hello(name):
    print(f'Hello{name:>10}')	
    
# 主程式
do_nothing()    # 呼叫函式
print_hello('John')
print_hello('小明')
print_hello('Joe')

範例

函式自訂函式(2/9)

# Mile2Km() 函式定義
def Mile2Km(speed):
    km = speed * 1.609
    return km

print('******球速對照表******')
for mile in range(90, 101):
    km = Mile2Km(mile)   # 函式呼叫
    print('%3d英里 = %5.1f公里' % (mile, km))

範例

******球速對照表******
 90英里 = 160.9公里
 91英里 = 160.9公里
 92英里 = 160.9公里
 93英里 = 160.9公里
 94英里 = 160.9公里
 95英里 = 160.9公里
 96英里 = 160.9公里
 97英里 = 160.9公里
 98英里 = 160.9公里
 99英里 = 160.9公里
100英里 = 160.9公里

執行結果

函式定義: def

函式呼叫

函式定義: def

函式呼叫

以return指定回傳值

小括弧內設定參數

基本觀念

若需要「回傳結果」,則使用return指令

函式自訂函式(3/9)

def 函式名稱(參數1, 參數2...):
    程式區塊   # 函式主體
    return 回傳值1, 回傳值2...

❶ 無參數

❷ 1個參數

def greeting( ):
    """無參數"""
    print("Python歡迎你")

# 主程式:呼叫
greeting( )
greeting( )
greeting( )
def greeting(name):
    """一個參數"""
    print("Hi " + name + ", Python歡迎你")

# 主程式:呼叫
greeting('張三' )
greeting('李四' )
greeting('王五' )

參數傳入

函式自訂函式(4/9)

❸ 多個參數

def AreaRectangle(width, height):
    """計算長方形面積"""
    return width * height

# 主程式開始
w = int(input('輸入長方形的寬度:'))
h = int(input('輸入長方形的高度:'))
print('寬長:%d %d,面積: %5d' % (w, h, AreaRectangle(w, h)))

參數傳入

函式自訂函式(5/9)

def greeting( ):
    """函數註解的方式:無參數,無回傳值的函式"""
    print("Python歡迎你")
    print("祝福學習順利")
    print("謝謝")

# 主程式:呼叫
greeting( )     # 不回傳值的函式呼叫方式
greeting( )
greeting( )
...
for mile in range(90, 101):
    km = Mile2Km(mile) # 有回傳值的呼叫方式
    print(f'{mile:3}英哩相當於{km:6.1f}')
...
...
def Mile2Km(speed):
    km = speed * 1.609
    return km
...

函數回傳

有回傳值以變數暫存供後續使用

函式自訂函式(6/9)

def CtoF(dc):
    return 32 + dc * 1.8

for dc in range(101):
    print('攝氏%3d度 = 華式%5.1f度' % (dc, CtoF(dc)))

練習:溫度轉換函式:攝氏轉華式

可直接return

攝氏  0度 = 華式 32.0
攝氏  1度 = 華式 33.8
攝氏  2度 = 華式 35.6
攝氏  3度 = 華式 37.4
攝氏  4度 = 華式 39.2

...

攝氏 97度 = 華式206.6
攝氏 98度 = 華式208.4
攝氏 99度 = 華式210.2
攝氏100度 = 華式212.0

執行結果

print()裡直接呼叫

函數回傳

函式自訂函式(7/9)

def AreaRectangle(width, height):   # 計算長方形面積
    return width * height

def AreaCircle(radius):             # 計算圓面積
    return 3.14159 * radius**2

while True:                         # 主程式開始
    choice = int(input('選擇功能:1.圓形, 2.長方形, 0.結束-->'))
    if choice == 0:
        break
    elif choice == 1:
        r = int(input('輸入圓半徑:'))
        print('半徑%d,面積:%8.2f' % (r, AreaCircle(r)))
    elif choice == 2:
        w = int(input('輸入長方形的寬度:'))
        h = int(input('輸入長方形的高度:'))
        print('寬長:%d %d,面積: %5d' % (w, h, AreaRectangle(w, h)))
    else:
        print('無此功能:', choice)
print('程式結束')

範例:面積計算(圓形,長方形)

選擇功能:1.圓形, 2.長方形, 0.結束-->1
輸入圓半徑:10
半徑10,面積:  314.16
選擇功能:1.圓形, 2.長方形, 0.結束-->2
輸入長方形的寬度:6
輸入長方形的高度:8
寬長:6 8,面積:    48
選擇功能:1.圓形, 2.長方形, 0.結束-->0
程式結束

執行結果

函數回傳

函式自訂函式(8/9)

撰寫一絕對值函式abs(),輸入任何正負值,都會得到正值。例如輸入-4得到4,輸入4也是得到4

練習1

練習2

設計加法函式add(),可將兩個數值相加,減法函式sub(),可將兩個數值相減。另設計指令0結束,1加法,2減法,做為主程式,並根據指令,輸入加法或減法所需的兩個數字。

函式自訂函式(9/9)

關鍵字參數 vs 位置性參數

def AreaRectangle(width, height):
    """計算長方形面積"""
    return width * height

# 主程式開始
w = int(input('輸入長方形的寬度:'))
h = int(input('輸入長方形的高度:'))
area0 = AreaRectangle(100, 200)           # 位置性參數, 需自己記住參數意義
area = AreaRectangle(height=h, width=w);  # 關鍵字參數: 順序可以與函式定義不一樣
print('寬長:%d %d,面積: %5d' % (w, h, area))

位置性參數:需記住參數意義

關鍵字參數:在呼叫函式時,可直接指定參數名稱

參數傳入

函式匿名函式lambda

lambda函式:一行、匿名(不用取函式名稱),取代小函式

lambda 參數: 函式本體

參數傳入

# 定義一個 lambda 函式來計算兩數之和
add = lambda a, b: a + b

# 調用 lambda 函式
result = add(10, 20)
print(f"兩數之和: {result}")

基本寫法, 即運算式

lambda 參數1,參數2: 函式本體

2個以上參數

(lambda 參數1: 函式本體)(值)

加上()給值,即可呼叫

練習

撰寫一個函式接受2個參數: s為開始數字, e為結束數字(包含),接著函式會印出介於s,e之間,所有4或9的倍數,並印出這些數字的總和

 

主程式輸入指令1時可重複輸入s,e兩組數字,直到輸入指令2,例如:

參數傳入

函式自訂函式: 多回傳值(1/3)

def 函式名稱(參數1, 參數2...):
    程式區塊   # 函式主體
    return 回傳值1, 回傳值2...
def maxmin(scores):      # 回傳最大值與最小值
    list2 = sorted(scores) # 排序: 小到大
    return list2[-1],list2[0]

list1 = [1, 9, 6 ,4 ,3]
big, small = maxmin(list1)
print('最大值:', big, '最小值:',small)
print('串列內容:', list1)

函式Function

  • 可回傳多個數值

範例

最大值: 9 最小值: 1
串列內容: [1, 9, 6, 4, 3]

執行結果

函數回傳

函式自訂函式: 多回傳值(2/3)

def CircleStat(radius):    # 計算圓周長與圓面積
    area = 3.14159 * radius**2
    circle = 2 * 3.14159 * radius
    return circle, area

while True:                         # 主程式開始
    r = int(input('輸入圓半徑(<=0結束):'))
    if r <= 0:
        break
    else:
        c, a = CircleStat(r)
        print('半徑%d,周長%8.2f, 面積:%8.2f' % (r, c, a))
print('程式結束')

範例:回傳圓周長與圓面積

輸入圓半徑(<=0結束):3
半徑3,周長   18.85, 面積:   28.27
輸入圓半徑(<=0結束):0
程式結束

執行結果

函數回傳

函式自訂函式: 多回傳值(3/3)

練習:輸入身高cm,換算為幾英尺幾英吋

# 以140公分為例: 使用整數除法, 餘數運算, 四捨六入函式round()
feet  = 140 // 30.48     # 整數除法, 結果為4
剩餘 = 140 % 30.48        # 餘數 18.08
inch = 剩餘 // 2.54       # 整數除法, 結果為7, 誤差大(不宜使用)
rinch = round(剩餘/2.54)  # 浮點數除法, 四捨六入(建議使用)
# round(): 四捨六入, 五->前一位奇數進位, 偶數不進位

函數回傳

函式自訂函式: 參數預設值(1/3)

def 函式名稱(參數1, 參數2=預設值):
    程式區塊   # 函式主體
    return 回傳值1, 回傳值2...

函式Function

  • 參數可設定預設值
  • 有預設值的參數需放在最後
def Mile2Km(speed=0):
    km = speed * 1.609
    return km

print(Mile2Km())     # 0.0
print(Mile2Km(90))   # 144.81

範例

def Mile2Km(speed):
    km = speed * 1.609
    return km

print(Mile2Km())     # 錯誤
print(Mile2Km(90))   

參數傳入

函式自訂函式: 參數預設值(2/3)

def Area(width, height=10):
    return width*height

print(Area(10,20)) # 有設定高度
print(Area(10))    # 使用預設高度

範例:有預設值的參數需放最後

200
100

執行結果

def Total(數量, 單價, 折扣=1.0):
    return 數量*單價*折扣

print(Total(10, 100))  # 數量10,單價100,無折扣
print(Total(5, 80, 0.6)) # 數量, 單價80, 折扣6折
1000.0
240.0

執行結果

參數傳入

函式自訂函式: 參數預設值(3/3)

def Menu():    # 印出預購折扣表
    print('='*10)
    print('1. 1杯無折扣')
    print('2. 10杯62折')
    print('3. 50杯58折')
    print('4. 99杯53折')
    print('0. 結束')
    print('='*10)

def Total(數量, 單價, 折扣=1.0):  # 計算總價與減價
    減價 = 數量*單價*(1.0-折扣)
    return 減價, 數量*單價*折扣   # 回傳 減價與總價

## 主程式
price = 45    # 單價45元
amount = [1, 10, 50, 99]  # 杯數串列
折扣數 = [1.0, 0.62, 0.58, 0.53]  # 折扣串列
while True:
    Menu()
    decision = int(input('你的選擇是:'))
    if decision == 0:
        print('程式結束')
        break
    elif decision>0 and decision<5:
        save, total = Total(amount[decision-1], price, 折扣數[decision-1])
        print('購買數量 %d, 總價%d, 節省%d' % (amount[decision-1], total, save))
    else: 
        print('選項輸入錯誤,請重新輸入')
==========
1. 1杯無折扣
2. 10杯62折
3. 50杯58折
4. 99杯53折
0. 結束
==========
你的選擇是:2
購買數量 10, 總價279, 節省171​

執行結果

參數傳入

函式自訂函式: 變數有效範圍

變數有效範圍

  • 全域變數: 定義於函式外,整個檔案有效
  • 區域變數: 定義於函式內,只在函式內有效
def Area(width, height):
    total = (width + height)*2 # 區域變數與函式外total名稱相同
    print('函式內:',total)
    return total, width*height

total = 100        # 全域變數
print(Area(10,20))
print('函式外:',total)

範例

遞迴(1/5)

遞迴Recursive

  • 函式執行過程中呼叫自己

範例

數學上定義n 階乘為「n!=n*(n-1)*(n-2)*(n-3)*⋯*3*2*1」

遞迴(2/5)

def fac(num):
    if num == 1:
        return 1
    else:
        return num*fac(num-1)

# 主程式
n = int(input('請輸入n值?'))
ans = fac(n)
print(n,'!為',ans,sep='')

範例

數學上定義n 階乘為「n!=n*(n-1)*(n-2)*(n-3)*⋯*3*2*1」

遞迴(3/5)

範例

求m 與n 的最大公因數,數學上可以使用輾轉相除法求解

遞迴(4/5)

def gcd(m, n):
    if m == 0:
        return n
    else:
        print(f'{m}與{n}的最大公因數相當於 {n % m}與{m}的最大公因數', sep='')
        return gcd(n % m, m)

# 主程式
m = int(input('請輸入m值?'))
n = int(input('請輸入n值?'))
ans = gcd(m, n)
print(m, '與', n, '的最大公因數為', ans, sep='')

範例

求m 與n 的最大公因數,數學上可以使用輾轉相除法求解

遞迴(5/5)

練習:請用遞迴函式設計費氏數列,規則如下:

  F = 0

  F = 1

  Fn = Fn-1 + Fn-2 (n>=2)

最後值應該是0, 1, 1, 2, 3, 5, 8, 13, 21, 34

Python內建函式

  • 字串函式
  • 數值函式

函式字串函式split()

字串分割函式: split()

  • 常用於英文斷詞
  • 預設以1個空格分隔, 但可設定分隔字元
['Welcome', 'to', 'the', 'Jungle']

執行結果

txt = "Welcome to the Jungle"
tList = txt.split()
print(tList)
date1 = "1999/2/3"
dList = date1.split('/')
print(dList)
['1999', '2', '3']

執行結果

以'/'字元分隔

函式字串函式join()

字串串接函式: join()

  • 連接字串
John#Peter#Vicky

執行結果

myTuple = ("John", "Peter", "Vicky")
x = "#".join(myTuple)
print(x)
myDict = {"name": "John", "country": "Norway"}
mySep = "TEST"
x = mySep.join(myDict)
print(x)
nameTESTcountry

執行結果

"分隔字串".join(串列)
"分隔字串".join(元組)
"分隔字串".join(字典)
score = ['40', '30', '80', '70', '50']
x = ",".join(score)       # score需為字串串列
print(x)
40,30,80,70,50

執行結果

函式字串函式find(), rfind()

字串搜尋函式: find(), rfind()

  • find(): 從左邊找到第一次出現的位置或回傳-1
  • rfind(): 從右邊找到第一次出現的位置或回傳-1
3
126

執行結果

myStr = """為提升博士級人才務實致用的研發能力,教育部推動產學博士相關計畫,搭起學界與產業界的橋梁,希望幫助博士生未來找到更好出路,至今已有554人參與。教育部今天舉行博士級研發人才培育成果發表會,邀請多位參與產學合作培育博士級研發人才計畫、大學產業創新研發計畫的博士生分享。"""

x = myStr.find('博士')
print(x)
y = myStr.rfind('博士')
print(y)
字串.find(要找的字串)
字串.rfind(要找的字串)

函式字串函式count()

字串統計函式: count()

  • 統計某字串出現的次數
6

執行結果

myStr = """為提升博士級人才務實致用的研發能力,教育部推動產學博士相關計畫,搭起學界與產業界的橋梁,希望幫助博士生未來找到更好出路,至今已有554人參與。教育部今天舉行博士級研發人才培育成果發表會,邀請多位參與產學合作培育博士級研發人才計畫、大學產業創新研發計畫的博士生分享。"""

total = myStr.count('博士')
print(total)
字串.count(要找的字串)

函式字串函式center()等

字串對齊函式: center(), rjust(), ljust()

  • 字串置中、靠右、靠左對齊
  春眠不覺曉   
     春眠不覺曉
春眠不覺曉     

執行結果

myStr = "春眠不覺曉"
print(myStr.center(10))   # 10位字元,置中對齊
print(myStr.rjust(10))    # 10位字元,靠右對齊
print(myStr.ljust(10))    # 10位字元,靠左對齊
字串.center(數值)  # 置中
字串.rjust(數值)   # 靠右對齊
字串.ljust(數值)   # 靠左對齊

函式字串函式strip()等

字串去除字元函式: strip(), rstrip(), lstrip()

  • 預設為去除空白字元
  • strip(): 同時移除左右兩側字元
  • 參數chars可指定多個字元
An Apple a day.
15
An Apple a day. 
16
 An Apple a day
15

執行結果

myStr = " An Apple a day. "
print(myStr.strip())  # 去除前後空格
print(len(myStr.strip()))
print(myStr.lstrip()) # 去除前方空格
print(len(myStr.lstrip()))
print(myStr.rstrip(" ."))  #去除右側空格與句點
print(len(myStr.rstrip(" .")))
字串.strip(chars)   # 移除左右兩側
字串.rstrip(chars)  # 移除右側
字串.lstrip(chars)  # 移除左側

Python程式設計

By Leuo-Hong Wang

Python程式設計

Lesson 8: 函式與遞迴

  • 1,385