函式
隨著程式功能越來越多,所撰寫的程式碼也會越來越龐大,此時要管理複雜的程式並不是很容易的事,此時可以利用函式來控制程式的複雜度。
提醒
本章節中原本有將訊息傳送給 Twitter 平台的範例,我將其修正為使用print()顯示訊息來模擬(為了不將時間花費在申請 Twitter 帳號)。
延續上一章的咖啡豆程式
功能需求變更:使用者希望程式可以提供兩種選項,一種是可以直接看到目前咖啡豆的價格(當咖啡豆的庫存太低時,只能緊急下單進貨);另一種則是維持舊有功能,每15分鐘取得一次咖啡豆的價格,直到價錢滿意為止才下單。
- 有兩種選項,程式必須根據使用者的選擇來執行相對應的程式碼,因此從第一章知道這必須使用 if/else 分支條件。
程式碼:
import time
price_now = input("Do you want to see the price now ?")
if(price_now == 'Y'):
fileName = "/Coffee.html"
file = open(fileName,'r')
text = file.read()
where = text.find('>$')
start_of_price = where + 2
end_of_price = start_of_price + 4
price = float(text[start_of_price:end_of_price])
print(price)
else:
price = 9999.0
while(price > 6.9):
time.sleep(5)
fileName = "/Coffee.html"
file = open(fileName,'r')
text = file.read()
where = text.find('>$')
start_of_price = where + 2
end_of_price = start_of_price + 4
price = float(text[start_of_price:end_of_price])
print(price)
print('Buy!')
當使用者想要馬上看到價格:

重利用而非重複
雖然上述的程式可以正確運行,不過可以看到中間有幾行程式碼一模一樣,假設客戶突然又增加了第三種、第四種報價選項,很快的程式碼將變得越來越長且可讀性越來越差,這樣的撰寫方式是不好的,因此請記得一件事:切勿重複你的程式碼!
- 重利用(Reuse) : 當你在複製程式碼的時候,只是在重複(Duplicate) 程式碼;但是重利用指得是只有單一份程式碼,你可以在任何需要的時候存取他。
- 函式:函式就是一種重利用的機制,隔離出一段程式碼區塊然後在需要的時候呼叫它。
- 定義方式:
def FunctionName():
code....
code....
- 位置:定義函式的位置很重要,必須將定義寫在你要呼叫它之前否則程式會無法辨識。
- 回傳值:函式使用 return()命令將函式處理完的資料回傳給呼叫此函式的程式碼。
重新整理一下
import time
def get_price():
fileName = "/Coffee.html"
file = open(fileName,'r')
text = file.read()
where = text.find('>$')
start_of_price = where + 2
end_of_price = start_of_price + 4
price = float(text[start_of_price:end_of_price])
return price
price_now = input("Do you want to see the price now ?")
if(price_now == 'Y'):
print(get_price())
else:
price = 9999.0
while(price > 6.9):
time.sleep(5)
price = get_price()
print(price)
print('Buy!')
可以看到上述程式碼變得簡潔且可讀性變高,這樣的程式較容易維護。
參數
- 功能需求變更:程式需要根據使用者所做的選擇,馬上傳送價格訊息給使用者的Twitter 頁面。
- 這時候我們定義一個函式為:send_to_twitter()
def send_to_twitter()
msg = "Coffee price is $"
print(msg)
程式碼:
import time
def get_price():
fileName = "/Coffee.html"
file = open(fileName,'r')
text = file.read()
where = text.find('>$')
start_of_price = where + 2
end_of_price = start_of_price + 4
price = float(text[start_of_price:end_of_price])
return price
def send_to_twitter():
msg = "Coffee price is $"
print(msg)
price_now = input("Do you want to see the price now ?")
if(price_now == 'Y'):
send_to_twitter()
else:
price = 9999.0
while(price > 6.9):
time.sleep(5)
price = get_price()
send_to_twitter()
print('Buy!')
執行結果


- 結果不管是什麼選擇,使用者收到的訊息都是一樣,但是沒有正確顯示價格訊息。看起來是因爲send_to_twitter() 函式並沒有收到價格,所以才沒有正確傳送訊息。
- 參數:參數(Parameter) 是你送給函式的值,我們將send_to_twitter()函式修正為可以接受價格參數的函式。
程式碼:
import time
def get_price():
fileName = "/Coffee.html"
file = open(fileName,'r')
text = file.read()
where = text.find('>$')
start_of_price = where + 2
end_of_price = start_of_price + 4
price = float(text[start_of_price:end_of_price])
return price
def send_to_twitter(price):
msg = "Coffee price is $"+ str(price)
print(msg)
price_now = input("Do you want to see the price now ?")
if(price_now == 'Y'):
send_to_twitter(get_price())
else:
price = 9999.0
while(price > 6.9):
time.sleep(5)
price = get_price()
send_to_twitter(price)
print('Buy!')
執行結果:

堆疊框架
功能需求變更:使用者想要為自己的Twitter帳號設定密碼,然後在要送出訊息給Twitter帳號時先檢查一下是否有密碼,有的話才傳訊訊息。
- 讓我們用學到的函式來增加功能,定義一個設定密碼函式為:set_password(),並且在程式最開始的時候就先呼叫此函式,好讓後續的程式可以取得此 password。
程式碼:
def set_password():
password = "C8H10N402"
set_password()
- 不過這時候執行程式時卻出現了:NameError: name 'password' is not defined。
- 這是因為當呼叫函式時,電腦會在堆疊框架上建立一組全新的變數,紀錄函式中所有用到的變數,而這些全新的變數被稱為本地參數(Local Variable) 。
- 堆疊機制好處就是函式中的變數獨立運算,不影響程式其他部分。
- 而當函式執行結束後,電腦會將此函式的堆疊框架丟棄,因此連同本地參數也都一併丟棄。
- set_password()執行時會創造一個新的本地參數password,但是執行後就被丟棄了,因此程式其他部分是看不到這個password參數的。