Lesson 8: 函式與遞迴
Last updated: 2024/10/8
發音: Func-shun
函式: 一段常需重複使用的程式碼
發音: 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)
函式定義好之後,不會直接執行,可重複呼叫使用
函式可接受參數、回傳計算值
def 函式名稱(參數1, 參數2...):
程式區塊 # 函式主體
return 回傳值1, 回傳值2...
def do_nothing():
pass # 不做任何事
# 主程式
do_nothing() # 呼叫函式
參數1, 參數2...可省略,()不可省略
視需要return回傳值,如不回傳return可省略
函式Function
範例
基本觀念
def do_nothing():
pass # 不做任何事
def print_hello(name):
print(f'Hello{name:>10}')
# 主程式
do_nothing() # 呼叫函式
print_hello('John')
print_hello('小明')
print_hello('Joe')
範例
# 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指令
def 函式名稱(參數1, 參數2...):
程式區塊 # 函式主體
return 回傳值1, 回傳值2...
❶ 無參數
❷ 1個參數
def greeting( ):
"""無參數"""
print("Python歡迎你")
# 主程式:呼叫
greeting( )
greeting( )
greeting( )
def greeting(name):
"""一個參數"""
print("Hi " + name + ", Python歡迎你")
# 主程式:呼叫
greeting('張三' )
greeting('李四' )
greeting('王五' )
參數傳入
❸ 多個參數
def AreaRectangle(width, height):
"""計算長方形面積"""
return width * height
# 主程式開始
w = int(input('輸入長方形的寬度:'))
h = int(input('輸入長方形的高度:'))
print('寬長:%d %d,面積: %5d' % (w, h, AreaRectangle(w, h)))
參數傳入
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
...
函數回傳
有回傳值以變數暫存供後續使用
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()裡直接呼叫
函數回傳
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
程式結束
執行結果
函數回傳
撰寫一絕對值函式abs(),輸入任何正負值,都會得到正值。例如輸入-4得到4,輸入4也是得到4
練習1
練習2
設計加法函式add(),可將兩個數值相加,減法函式sub(),可將兩個數值相減。另設計指令0結束,1加法,2減法,做為主程式,並根據指令,輸入加法或減法所需的兩個數字。
關鍵字參數 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 函式來計算兩數之和
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,例如:
參數傳入
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]
執行結果
函數回傳
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
程式結束
執行結果
函數回傳
練習:輸入身高cm,換算為幾英尺幾英吋
# 以140公分為例: 使用整數除法, 餘數運算, 四捨六入函式round()
feet = 140 // 30.48 # 整數除法, 結果為4
剩餘 = 140 % 30.48 # 餘數 18.08
inch = 剩餘 // 2.54 # 整數除法, 結果為7, 誤差大(不宜使用)
rinch = round(剩餘/2.54) # 浮點數除法, 四捨六入(建議使用)
# round(): 四捨六入, 五->前一位奇數進位, 偶數不進位
函數回傳
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))
參數傳入
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
執行結果
參數傳入
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)
範例
遞迴Recursive
範例
數學上定義n 階乘為「n!=n*(n-1)*(n-2)*(n-3)*⋯*3*2*1」
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」
範例
求m 與n 的最大公因數,數學上可以使用輾轉相除法求解
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 的最大公因數,數學上可以使用輾轉相除法求解
練習:請用遞迴函式設計費氏數列,規則如下:
F₀ = 0
F₁ = 1
Fn = Fn-1 + Fn-2 (n>=2)
最後值應該是0, 1, 1, 2, 3, 5, 8, 13, 21, 34
字串分割函式: split()
['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()
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()
3
126
執行結果
myStr = """為提升博士級人才務實致用的研發能力,教育部推動產學博士相關計畫,搭起學界與產業界的橋梁,希望幫助博士生未來找到更好出路,至今已有554人參與。教育部今天舉行博士級研發人才培育成果發表會,邀請多位參與產學合作培育博士級研發人才計畫、大學產業創新研發計畫的博士生分享。"""
x = myStr.find('博士')
print(x)
y = myStr.rfind('博士')
print(y)
字串.find(要找的字串)
字串.rfind(要找的字串)
字串統計函式: count()
6
執行結果
myStr = """為提升博士級人才務實致用的研發能力,教育部推動產學博士相關計畫,搭起學界與產業界的橋梁,希望幫助博士生未來找到更好出路,至今已有554人參與。教育部今天舉行博士級研發人才培育成果發表會,邀請多位參與產學合作培育博士級研發人才計畫、大學產業創新研發計畫的博士生分享。"""
total = myStr.count('博士')
print(total)
字串.count(要找的字串)
字串對齊函式: center(), rjust(), ljust()
春眠不覺曉
春眠不覺曉
春眠不覺曉
執行結果
myStr = "春眠不覺曉"
print(myStr.center(10)) # 10位字元,置中對齊
print(myStr.rjust(10)) # 10位字元,靠右對齊
print(myStr.ljust(10)) # 10位字元,靠左對齊
字串.center(數值) # 置中
字串.rjust(數值) # 靠右對齊
字串.ljust(數值) # 靠左對齊
字串去除字元函式: strip(), rstrip(), lstrip()
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) # 移除左側