21 Python 函式實戰
模組化程式設計是指在進行程式設計時將一個大程式按照功能劃分為若干小程式模組,每個小程式模組完成一個確定的功能,並在這些模組之間建立必要的聯絡,通過模組的互相協作完成整個功能的程式設計方法。
在設計較複雜的程式時,一般採用自頂向下的方法,將問題劃分為幾個部分,各個部分再進行細化,直到分解為較好解決問題為止。
採用模組化設計編寫程式時,不是一開始就逐條編寫程式程式碼,而是首先用主程式、子程式等框架把軟體的主要結構和流程描述出來。以功能塊為單位進行程式設計,實現其求解演算法的方法稱為模組化。
利用函式,不僅可以實現程式的模組化,使得程式設計更加簡單和直觀,從而提高了程式的易讀性和可維護性,而且還可以把程式中經常用到的一些計算或操作編寫成通用函式,以供隨時呼叫。
本小節實現一個通訊錄管理程式。在前面章節中,程式的各項功能程式碼全部集中在一個程式碼段中,程式的結構不清晰。本小節使用函式來實現程式,採用模組化的程式設計方法:
- 劃分通訊錄程式的功能模組,使用函式實現相應的功能
- 首先實現整體框架,然後再細化每個功能細節
- 最終的程式由多個函式構成,每個函式實現一個單一的功能,整個程式的結構清晰
1. 通訊錄功能簡介
編寫程式 addr-manage.py 實現通訊錄管理系統,通訊錄包含若干聯絡人,每個聯絡人包括:姓名、地址、電話 3 項內容。程式提供 4 項基本功能:
- 增加聯絡人: 使用者輸入姓名、地址、電話等資訊,將資訊儲存在一個列表中
- 列出聯絡人: 列印輸出所有聯絡人的資訊
- 查詢聯絡人: 使用者輸入聯絡人姓名,列印輸出該聯絡人的資訊
- 刪除聯絡人: 使用者輸入聯絡人姓名,從通訊錄中刪除該聯絡人
通過命令列介面實現以上功能,程式 addr-manage.py 執行時首先列印一個選單,如下所示:
C:\> python addr-manage.py
1. create person
2. list all persons
3. query person
4. delete person
5. quit
Enter a number(1-5):
總共有 5 個選項,使用者輸入對應的數字選擇相應的功能,如下表所示:
數字選項 | 功能描述 |
---|---|
1. create person | 增加聯絡人 |
2. list all persons | 列出聯絡人 |
3. query person | 查詢聯絡人 |
4. delete person | 刪除聯絡人 |
5. quit | 退出通訊錄程式 |
2. 程式框架
2.1 資料結構
程式使用字典描述一個聯絡人,假設某個聯絡人的資訊如下:
姓名 | 地址 | 電話 |
---|---|---|
張三 | 南京 | 12306 |
使用字典描述該聯絡人如下:
>>> person = {'name': '張三', 'address': '南京', 'phone': '12306'}
- 字典有三個鍵:name、address、phone
- 對應的值分別為:張三、南京、12306
程式將所有聯絡人資訊儲存在列表中,即通訊錄是一個列表、列表的元素是字典。假設通訊錄中有兩個人,它們的資訊如下所示:
姓名 | 地址 | 電話 |
---|---|---|
張三 | 南京 | 12306 |
李四 | 王五 | 10086 |
使用列表描述通訊錄如下:
>>> zhangSan = {'name': '張三', 'address': '南京', 'phone': '12306'}
>>> liSi = {'name': '李四', 'address': '北京', 'phone': '10086'}
>>> persons = [zhangSan, liSi]
- 在第 1 行,變數 zhangSan 的型別是一個字典,描述了張三的資訊
- 在第 2 行,變數 liSi 的型別是一個字典,描述了李四的資訊
- 在第 3 行,persons 是一個列表,儲存了 zhangSan 和 liSi 兩個聯絡人
上面的程式碼為了易於理解,使用了 3 行程式碼描述了通訊錄。也可以使用 1 行程式碼描述該通訊錄,程式碼如下:
>>> persons = [{'name': '張三', 'address': '南京', 'phone': '12306'}, {'name': '李四', 'address': '北京', 'phone': '10086'}]
2.2 劃分功能模組
分析通訊錄的功能需求,初步將程式劃分為 5 個功能模組,如下表所示:
功能模組 | 對應的函式 |
---|---|
增加聯絡人 | create_person |
列出聯絡人 | list_person |
查詢聯絡人 | query_person |
刪除聯絡人 | delete_person |
主控模組 | main |
編寫對應的函式,這裡先寫出函式的定義,暫時忽略實現,程式碼如下:
persons = []
def create_person():
pass
def list_person():
pass
def query_person():
pass
def delete_person():
pass
def main():
pass
main()
- 在第 1 行,定義全域性變數 persons,persons 是一個列表,儲存了所有聯絡人的資訊
- 在第 3 行,定義函式 create_person,該函式實現 “增加聯絡人” 的功能
- 在第 6 行,定義函式 list_person,該函式實現 “列出聯絡人” 的功能
- 在第 9 行,定義函式 query_person,該函式實現 “查詢聯絡人” 的功能
- 在第 12 行,定義函式 delete_person,該函式實現 “刪除聯絡人” 的功能
- 在第 15 行,定義函式 main,該函式控制程式的流程,被稱為主控函式,他讀取使用者的選擇,呼叫相應的功能,實現對通訊錄的增、刪、查的操作
- 在第 18 行,程式啟動後,首先執行主函式 main
2.3 主功能模組
本節完成程式的主功能模組 main,函式 main 的功能邏輯如下:
- 獲取使用者輸入的選擇
- 根據使用者的選擇執行對應的功能
- 重複執行第 1 步的操作
函式 main 的實現程式碼如下:
persons = []
def get_choice():
pass
def main():
while True:
choice = get_choice()
if choice == '1':
create_person()
elif choice == '2':
list_person()
elif choice == '3':
query_person()
elif choice == '4':
delete_person()
elif choice == '5':
break
else:
print('Invalid choice')
main()
- 在第 1 行,建立一個空列表 persons,persons 記錄所有聯絡人的資訊
- 在第 3 行,定義了函式 get_choice,該函式列印功能選單並讀取使用者的選擇
- 在第 6 行,定義了函式 main,該函式讀取使用者選擇,並執行相應功能
- 在第 7 行,建立一個 while 死迴圈
- 在第 8 行,使用 get_choice() 函式獲取使用者輸入的選擇
- 在第 10 行至第 21 行,根據 choice 選擇執行相應的功能
- 在第 19 行,如果 choice == ‘5’,則執行 break 退出程式
2.4 獲取使用者輸入
編寫函式 get_choice 獲取使用者的選擇,程式碼如下:
def get_choice():
print('1. create person')
print('2. list all persons')
print('3. query person')
print('4. delete person')
print('5. quit')
choice = input('Enter a number(1-5):')
return choice
- 在第 2 行到第 6 行,列印功能選單
- 在第 7 行,使用 input() 函式獲取使用者輸入的選擇
- 在第 8 行,返回使用者的選擇 choice
3. 增加聯絡人
本小節實現增加聯絡人的功能,如下所示:
def create_person():
name = input('name: ')
address = input('address: ')
phone = input('phone: ')
person = {'name': name, 'address': address, 'phone': phone}
persons.append(person)
- 在第 1 行,定義函式 create_person,該函式實現增加聯絡人的功能
- 在第 2 行,獲取使用者輸入的 name
- 在第 3 行,獲取使用者輸入的 address
- 在第 4 行,獲取使用者輸入的 phone
- 在第 5 行,根據使用者輸入的 name、address、phone 建立一個字典,用於描述該聯絡人
- 在第 6 行,將聯絡人加入到 persons 中
4. 列出聯絡人
本小節實現列出所有聯絡人的功能,如下所示:
def list_person():
for person in persons:
print('%s,%s,%s' % (person['name'], person['address'], person['phone']))
- 在第 1 行,定義函式 list_person,實現列出所有聯絡人的功能
- 在第 2 行,遍歷列表 persons,迴圈變數 person 是一個字典
- 在第 3 行,列印變數 person 的內容
對每個聯絡人列印輸出一行,假設通訊錄中已經儲存了張三和李四兩個聯絡人,輸出如下:
C:\> python addr-manage.py
1. create person
2. list all persons
3. query person
4. delete person
5. quit
Enter a number(1-5): 2
張三,南京,12306
李四,北京,10086
- 在第 7 行,使用者選擇執行功能 2
- 在第 8 行,列印聯絡人張三的資訊
- 在第 9 行,列印聯絡人李四的資訊
- 查詢聯絡人
本小節實現查詢聯絡人的功能,如下所示:
def query_person():
name = input('name: ')
for person in persons:
if person['name'] == name:
print('%s,%s,%s' % (person['name'], person['address'], person['phone']))
- 在第 1 行,定義函式 query_person,實現查詢聯絡人的功能
- 在第 2 行,獲取使用者輸入的 name
- 在第 3 行,遍歷列表 persons,迴圈變數 person 是一個字典
- 在第 4 行,如果使用者輸入的 name 和迴圈訪問 person 的 name 相同,則表示找到指定的 person
- 在第 5 行,列印變數 person 的內容
6. 刪除聯絡人
本小節實現刪除聯絡人的功能,如下所示:
def delete_person():
name = input('name: ')
for person in persons:
if person['name'] == name:
persons.remove(person)
break
- 在第 1 行,定義函式 delete_person,實現刪除聯絡人的功能
- 在第 2 行,獲取使用者輸入的 name
- 在第 3 行,遍歷列表 persons,迴圈變數 person 是一個字典
- 在第 4 行,如果使用者輸入的 name 和迴圈訪問 person 的 name 相同,則表示找到指定的 person
- 在第 5 行,使用方法 persons.remove(person), 從 persons 中刪除元素 person
- 在第 6 行,退出 for 迴圈
7. 完整的程式
persons = []
def create_person():
name = input('name: ')
address = input('address: ')
phone = input('phone: ')
person = {'name': name, 'address': address, 'phone': phone}
persons.append(person)
def list_person():
for person in persons:
print('%s,%s,%s' % (person['name'], person['address'], person['phone']))
def query_person():
name = input('name: ')
for person in persons:
if person['name'] == name:
print('%s,%s,%s' % (person['name'], person['address'], person['phone']))
def delete_person():
name = input('name: ')
for person in persons:
if person['name'] == name:
persons.remove(person)
break
def get_choice():
print('1. create person')
print('2. list all persons')
print('3. query person')
print('4. delete person')
print('5. quit')
choice = input('Enter a number(1-5):')
return choice
def main():
while True:
choice = get_choice()
if choice == '1':
create_person()
elif choice == '2':
list_person()
elif choice == '3':
query_person()
elif choice == '4':
delete_person()
elif choice == '5':
break
else:
print('Invalid choice')
main()
8. 小結
這節課我們通過使用函式的方式來改寫了我們之前所設計的通訊錄功能,可以把這一小節的程式碼和之的程式碼做一下比對,看一下函數語言程式設計與普通程式設計正規化有何不同。