Python 入門指南 5.0

單元 22 - Encrypt 類別

~~學習進度表~~

類別 (class) 為 Python 開發軟體 (software) 的要角,因為類別用來設計物件 (object) ,軟體的實際運作則是藉由物件與物件的互動。我們接下來進入實際開發軟體的階段,到 GUI 篇會發展出一個 GUI 軟體,而在「Brython 篇」會把發展出的 Encrypt 類別應用在網頁 App 中

     Encrypt
         ⇘
       EncryptController

我們打算發展的一個替英文句子編密碼的軟體,主要功能是做小寫字母的替換,例如 "There is no spoon." 可能變成以下任一個

  
  
  
  
  
Tfqdq ki jo itooj.
Tcnan hf gl fqllg.
Tczmz dn ij nkjji.
Tgfsf pb ir barri.
Tdcpc my fo yxoof.

首先,我們要發展 Encrypt 類別,主要功能是建立一個英文小寫字母的對換表格,藉由這個表格,我們可以將英文句子中的小寫英文字母進行對換,然後開發圖形使用者介面 (graphical user interface) 的 EncryptGUI 類別。

GUI 的外觀如下圖

我們的 GUI 設計採用標準程式庫 (standard library) 的 Tk ,主要原因是 Tk 直建內建在 Python 官方直譯器 (interpreter) 中,無須額外整合第三方程式庫 (third party library) 。

有兩個可供輸入的文字欄位 (text field) ,其中一個我們作為輸出的顯示訊息之用,另有三個標籤 (label) ,顯示文字的提示訊息,七個按鈕 (button) ,提供 新建開啟儲存 Encrypt 物件,與 編碼解碼 所輸入的英文句子, 清除 所有輸入欄位,以及 拷貝 輸出結果等的功能。

最後在 Brython 篇,把原本在 GUI 的功能移植到網頁上,利用瀏覽器 (browser) 進行編碼及解碼的功能

Brython 為第三方程式庫,立意是直接在瀏覽器中執行 Python 程式,用以取代 JavaScript 。

現在我們先來看看所有功能的核心,也就是 Encrypt 類別,我們的目的是,建立一個小寫英文字母的轉換表格,然後編碼、解碼都可直接依據這個表格。我們打算用下面的數學公式建立表格

  
  
  
y = a * x + b
m = y % n
r = m + diff

這裡的概念是利用字元的 Unicode 編碼順序,假設 x 為字元的原始編碼, Unicode 編碼中 'a'97 ,然後將 x 乘上變數 (variable) a , 再加上變數 b ,假設兩者均是 09 的隨機整數,這樣便得到 y 的值。

然後將 y 除以 n 取得餘數 mn 為所要轉換的字元數量,英文小寫字母共有 26 個,所以這裡 n 等於 26 ,因此 m 等於 025 之間的整數值。最後將 m 加上 diffdiff 也就是編碼系統的差值,由於 Unicode 中 'a'97 ,所以這裡 diff 要以 97 代入。

因此,餘數 0 的字元會替換成 'a' ,餘數 1 的字元會被替換成 'b' ,餘數 2 的字元會被替換成 'c' ,餘下 23 個字元類推。這樣的計算需要進行 n 次,也就是 26 次,我們最後得到一組餘數與相對應字元的表格,這就是我們需要的表格了。

重複 n 次,我們需要一個迴圈 (loop) ,由於重複次數確定,因此 while 迴圈 (while loop) 就可以了,那我們要用什麼東西來儲存這個表格呢? Python 有很多內建的資料結構 (data structure) ,可以依資料特性有效率的處理資料,這裡,我們利用字串 (string) 就可以了。

字串就像是不可變的 (immutable) 串列 (list) ,這意思是說,字串可像串列用索引值存取裡頭的元素 (element) ,也就是長度為 1 的子字串,索引值恰巧是從 0 開始,這也完全符合我們計算餘數從 0 開始的需求。

我們先寫個開發規格的版本,如下

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
# 定義 Encrypt 類別
class Encrypt:
    # 定義建構子
    def __init__(self):
        # 建立密碼表
        self.set_code()

    # _code 的 getter
    @property
    def code(self):
        return self.__code

    # _code 的 setter
    def set_code(self):
        self.__code = "code"

    # 編碼的方法
    def toEncode(self, str):
        pass

    # 解碼的方法
    def toDecode(self, str):
        pass

# 測試部分
if __name__ == '__main__':
    e = Encrypt()
    print()
    print(e.code)
    print()

# 檔名: encrypt01.py
# 說明:《Python入門指南》的範例程式
# 網站: http://kaiching.org
# 作者: 張凱慶
# 時間: 2023 年 5 月

Encrypt__init__() 就是呼叫 setcode()

 4
 6
    def __init__(self):
        self.set_code()

密碼表預計儲存在封裝後的 __code 屬性 (attribute) ,這裡 setcode() 先簡單指派 "code" 字串給 __code

14
15
    def set_code(self):
        self.__code = "code"

由於 __code 被封裝 (encapsulation) ,由於 __code 屬性在後續還是需要印出來查看是否正確,因此額外設定 code 屬性,回傳 __code

 9
10
11
    # _code 的 getter
    @property
    def code(self):
        return self.__code

這樣一來,底下測試部分就可以直接印出 code

26
27
28
29
30
if __name__ == '__main__':
    e = Encrypt()
    print()
    print(e.code)
    print()

負責編碼與解碼的 toEncode()toDecode() 方法則是先寫出來,關鍵字 (keyword) pass 表示什麼事都不做的陳述 (statement)

18
19
22
23
    def toEncode(self, str):
        pass
    def toDecode(self, str):
        pass

encrypt01.pyEncrypt 類別基本的規格,接下來我們把公式放進 setcode() ,來建立實際的密碼表囉!

中英文術語對照
屬性attribute
瀏覽器browser
按鈕button
類別class
資料結構data structure
元素element
封裝encapsulation
圖形使用者介面graphical user interface
不可變的immutable
直譯器interpreter
關鍵字keyword
標籤label
串列list
迴圈loop
物件object
標準程式庫standard library
陳述statement
字串string
軟體software
文字欄位text field
第三方程式庫third party library
while 迴圈while loop
變數variable
重點整理
1. Encrypt 類別的主類功能是轉換句子中的英文小寫字母,最後作為 GUI 軟體的核心部分。
2. Encrypt 類別以數學公式建立英文字母的轉換表格,用字串當實體屬性儲存表格。
3. Python 中有許多內建的資料結構,字串像是不可變的串列,可用索引值存取長度為 1 的子字串。
4. Unicode 中, 'a' 的整數值為 97
5. 關鍵字 pass 是什麼事都不做的陳述。
6. 軟體規格是依據需求制定的功能表列。
問題與討論
1. 為什麼 Encrypt 類別是要當作 GUI 軟體的核心?不能讓 Encrypt 類別直接成為大展神威的 GUI 軟體嗎?
2. 除了數學公式外,有其他的方式可以建立轉換表格嗎?
3. 為什麼程式的發展要逐步來?不能一次到位嗎?
練習
1. 寫一個程式 exercise2201.py ,定義繼承自 ExceptionParameterError ,在 __str__() 部分回傳 "參數型態錯誤" ,執行部分直接發起 ParameterError 例外。 參考程式碼
2. 承上題,將新程式寫在 exercise2202.py 中,定義比較參數大小的函數 higher() ,檢查參數是否為整數,如果參數不是整數就發起 ParameterError ,反之回傳比較結果。 參考程式碼
3. 承上題,將新程式寫在 exercise2203.py 中,在命令列接收使用者輸入,比較跟固定數字例如 100 的大小。。 參考程式碼
4. 承上題,將新程式寫在 exercise2204.py 中,利用標準程式庫中 randomrandint() 取得 199 之間的整數,然後取得使用者輸入的數字,將隨機數字跟輸入數字比較大小。 參考程式碼
5. 承上題,將新程式寫在 exercise2205.py 中,改成比大小的遊戲。 參考程式碼
6. 承上題,將新程式寫在 exercise2206.py 中,改成猜數字遊戲。 參考程式碼
7. 承上題,將新程式寫在 exercise2207.py 中,加入 while True 迴圈,直到使用者猜對才結束遊戲。 參考程式碼
8. 承上題,將新程式寫在 exercise2208.py 中,加入 count 變數記錄猜測次數。 參考程式碼
9. 承上題,將新程式寫在 exercise2209.py 中,加入使用者猜測大或小的提示。 參考程式碼
10. 承上題,將新程式寫在 exercise2210.py 中,將猜數字遊戲定義放到函數 guess_game() 中。 參考程式碼

上一頁 單元 21 - 非同步程式設計與認識標準程式庫
回 Python 入門指南 5.0 首頁
下一頁 單元 23 - 實作 setcode()
回 Python 教材首頁
回程式語言教材首頁