# 4. 模組與類別 模組的好處: 1. 抽象層的封裝與隔離 2. 儲存物件的狀態 3. 擁有自己的名稱空間 4. 容易重用、功能拆分,更容易透過團隊協同開發專案 ## 4.1 建立模組 Python的「.py」檔本身就是一個模組,所以模組是Python最自然的抽象層。 透過`import`指令就可以把模組內的變數、物件和函式引入使用;當`import`某個模組會使該被指定的「.py」檔被載入時,Python直譯器會為這個檔案建立一個module實例(instance),並賦予一個名字可以用來參考它。 ##### `dir()` `dir()`函式可以列出一個模組內有哪些名稱: ``` import math dir(math) ``` > 如果呼叫`dir()`函式的時候沒有帶入模組名稱,會查詢目前所在模組的名稱。 ### 4.1.1 `from ... import ...` 也可以用下面的方式將指定的模組內的名稱匯入: ``` for foo import x print(x) import foo print(foo.x) ``` 如果是使用`*`結尾,將會匯入模組內所有名稱,如果有變數不想被匯入,可以加上底線開頭,例如: ``` x = 1 _y = 2 # 將不會被匯入 z = 3 ``` ``` from foo import * print(x) print(_y) # NameError ``` ##### `__all__` 定義`__all__`清單可以直接指定可以被`import`的名稱,例如: ``` __all__ = ['x', 'y'] ``` 變數`x`、`y`將被匯入。 ### 4.1.2 `del 模組名稱` `del`除了可以刪除變數外,也可以刪除模組,因為透過`import`建立的名稱,其實也是建立變數,因此可以將透過`import`進來的模組刪除。 ``` import foo del foo from foo import x del x ``` > `del`只是刪除名稱,而不是將模組刪除 ##### `sys.modules` 想要知道目前載入的名稱與實力有哪些,可以透過`sys.modules`,例如: ``` import sys import foo 'foo' in sys.modules del foo sys.modules['foo'].x ``` > `import`也可以加上`if`條件式,用來在不同的情況下`import`不同的模組 ## 4.2 類別 ### 4.2.1 定義類別 ``` class MyClass: pass myClass = MyClass() ``` ### 4.2.2 定義方法 ``` class MyClass: def plus(self, a, b): return a + b myClass = MyClass() print(myClass.plus(10, 20)) ``` 在類別內所有的方法第一個參數都是`self` ### 4.2.3 定義`__init__()`方法 `__init()`方法可以將該類別的初始化流程都定義在裡面,該方法在建立類別物件的時候會自動被呼叫。 ``` class MyClass: def __init__(self): self.x = 99 self.y = 88 def show(self): print(self.x) print(self.y) myClass = MyClass() myClass.show() ``` > 請注意`__init__()`方法前後都是兩個底線。 ##### `__str()__`方法 透過定義`__str__()`方法,可以在該物件透過呼叫`str()`函式時輸出自訂的字串,例如: ``` class MyClass: def __str__(self): return 'Hello, Class!' myClass = MyClass() print(str(myClass)) ``` > 請注意,該方法一定要回傳一個字串。 ## 4.3 實作 ### 4.3.1 題目 開發一個學生成績管理系統,有三個主要功能: 1. 管理學生成績 2. 查詢學生成績 3. 關於 ##### 管理學生成績 有兩個子功能: 1. 新增學生成績:學號、姓名、國文、英文、數學 2. 刪除學生成績:可以輸入學號或姓名來刪除 ##### 查詢學生成績 有兩個子功能: 1. 依學號查詢 2. 顯示全部成績 > 1. 成績查詢皆會自動加總分數 > 2. 子選單需要有回主選單功能 > 3. 主選單需要有離開功能 ### 4.3.2 程式碼 ##### 無函式版: ``` grades = {} # 空的dict(字典) while True: print('===================') print('學生成績管理系統') print('===================') print('1. 管理學生成績') print('2. 查詢學生成績') print('3. 關於') print('4. 離開') cmd = input('==>') if cmd == '1': # 管理學生成績 while True: print('===================') print('子選單: 管理學生成績') print('===================') print('1. 新增學生成績') print('2. 刪除學生成績') print('3. 回主選單') sub_cmd = input('==>') if sub_cmd == '1': # 新增學生成績 num = input('請輸入學號: ') name = input('請輸入姓名: ') mandiran = int(input('請輸入國文成績: ')) # int()轉成數字 math = int(input('請輸入數學成績: ')) english = int(input('請輸入英文成績: ')) # 新增一筆成績 grades[num] = [name, mandiran, math, english] #print(grades) # for 開發時除錯用 print('新增完成!') elif sub_cmd == '2': # 刪除學生成績 num = input('請輸入要刪除成績的學號: ') if num in grades.keys(): del grades[num] print('刪除完成!') else: print('查無此人!') #print(grades) # for 開發時除錯用 elif sub_cmd == '3': # 回主選單 break elif cmd == '2': # 查詢學生成績 while True: print('===================') print('子選單: 查詢學生成績') print('===================') print('1. 依學號查詢') print('2. 顯示全部成績') print('3. 回主選單') sub_cmd = input('==>') if sub_cmd == '1': # 依學號查詢 num = input('請輸入要查詢成績的學號: ') if num in grades.keys(): grade = grades[num] print('學號', num, ', ', grade[0], '的成績: 國文=', grade[1], \ ', 數學=', grade[2], ', 英文=', grade[3], ', 總分: ', \ grade[1] + grade[2] + grade[3]) else: print('查無此人!') elif sub_cmd == '2': # 顯示全部成績 if len(grades) == 0: print('無學生成績資料') else: for num, grade in grades.items(): print('學號', num, ', ', grade[0], '的成績: 國文=', grade[1], \ ', 數學=', grade[2], ', 英文=', grade[3], ', 總分: ', \ grade[1] + grade[2] + grade[3]) elif sub_cmd == '3': # 回主選單 break elif cmd == '3': # 關於 print('學生成績管理系統') print('版本: 0.01') print('日期: 2020-08-01') print('開發者: Aaron Ho') elif cmd == '4': # 離開 break else: print('輸入錯誤!') ``` ##### 函式版 students_system.py ``` grades = {} def student_system(): while True: print('-------------------') print('學生成績管理系統') print('-------------------') print('1. 管理學生成績') print('2. 查詢學生成績') print('3. 結束') c = input('=> ') if c == '1': func_1() elif c == '2': func_2() elif c == '3': break else: print('輸入錯誤!') def func_1(): while True: print('-------------------') print('管理學生成績') print('-------------------') print('1. 新增學生成績') print('2. 刪除學生成績') print('3. 回主功能表') c = input('=> ') if c == '1': add_grade() elif c == '2': del_grade() elif c == '3': break else: print('輸入錯誤!') def func_2(): while True: print('-------------------') print('查詢學生成績') print('-------------------') print('1. 依學號查詢') print('2. 查詢全部成績') print('3. 回主功能表') c = input('=> ') if c == '1': find_grade() elif c == '2': show_grades() elif c == '3': break else: print('輸入錯誤!') def add_grade(): n = input('請輸入學號: ') name = input('請輸入學生姓名: ') mandrain = input('請輸入國文成績: ') math = input('請輸入數學成績: ') english = input('請輸入英文成績: ') grades[n] = [name, mandrain, math, english] print('新增完成!') def del_grade(): n = input('請輸入要刪除的學號: ') if n in grades.keys(): del grades[n] print('刪除完成.') else: print('查無此人.') def find_grade(): n = input('請輸入要查詢的學號: ') if n in grades.keys(): grade = grades[n] print('學號: ', n, ', ', grade[0], '的成績: 國文=', grade[1], ', 數學=', grade[2], ', 英文=', grade[3]) else: print('查無此人.') def show_grades(): if len(grades) == 0: print('無學生成績.') return for n, grade in grades.items(): print('學號: ', n, ', ', grade[0], '的成績: 國文=', grade[1], ', 數學=', grade[2], ', 英文=', grade[3]) ``` main.py ``` import student_system st = student_system st.student_system() ``` #### 練習 1. 請將學生成績管理系統改為類別版本。