Python 入門指南

單元 18 - 編碼

~~學習進度表~~

編碼 (encoding) 需要用到轉換表格,我們利用字串 (string) 儲存這個表格,簡單說,就是利用 Unicode 排列順序,對應到表格中該位置的字元

There is no spoon.
×                 

012345678910111213141516171819202122232425
qzirajsbktcludmvenwfoxgpyh

上圖是用了如下的表格

code = "qzirajsbktcludmvenwfoxgpyh"

我們先來想一想程式如何完成編碼工作,假設是對以下的字串 (string) 進行編碼

"There is no spoon."

首先, 'T' 不是英文小寫字母,因此跳過,然後 'h''e''r''e' 都是英文小寫字母,對照表格,需要轉換為 'b''a''n''a' ,接下來遇到一個空格字元 ' ' ,也跳過,然後 'i''s' 也都是英文小寫字母,需要轉換為 'k''w' ,餘下類推。

所以需要利用一個迴圈 (loop) 進行上述編碼工作,逐一檢查字串中的每一個字元,若是屬於英文小寫字母的編碼範圍就是 Unicode 編碼 97122 之間,我們先將該字元轉換為整數,然後減掉 97 就會是表格字串中對應字元索引值。

這是說,第 0 個字元(索引值為 0'T' 不在英文小寫字母編碼的範圍,因此程式不會處理,然後到第 1 個字元 'h' ,這是英文小寫字母編碼為 104 ,減去 97 之後為 7 ,對應到上面的表格會是 'b' ,因此得到的新字串1 個新字元就是 'b' ,餘下會一直進行重複的工作到字串結束為止。

因此,我們在 encrypt06.py 加入 toEncode() 的設計

# 使用 randint()
import random

# 定義 Encrypt 類別 
class Encrypt:
  def __init__(self):
    self.setcode()
    
  def setcode(self):
    # 取得 a 、 b 值
    a = 0
    b = 0
    while a % 2 == 0:
      a = random.randint(0, 9)
      b = random.randint(0, 9)

    # 利用公式建立密碼表
    self.code = ""
    c = "a"
    i = 0
    while i < 26:
      x = c
      y = ord(x) * a + b
      m = y % 26
      self.code += chr(m + 97)
      c = chr(ord(c) + 1)
      i += 1
    
  def getcode(self):
    return self.code
    
  # 編碼的方法
  def toEncode(self, str):
    # 暫存編碼結果的字串
    result = ""
    
    # 利用迴圈走完參數字串的所有字元
    for c in str:
      # 判斷該字元是否為英文小寫字母
      # 若是英文小寫字母就進行編碼轉換
      c1 = ord(c) >= 97
      c2 = ord(c) <= 122
      if c1 and c2:
        m = ord(c) - 97
        result += self.code[m]
      else:
        result += c
        
    # 結束回傳編碼過的字串
    return result
    
  # 解碼的方法
  def toDecode(self, str):
    pass
    
# 測試部分
if __name__ == '__main__':
  e = Encrypt()
  print()
  print(e.getcode())
  s1 = "There is no spoon."
  print("Input : " + s1)
  s2 = e.toEncode(s1)
  print("Encode: " + s2)
  print()
  
#《程式語言教學誌》的範例程式
# http://kaiching.org/
# 檔名:encrypt06.py
# 功能:示範利用 Python 設計 Encrypt 類別
# 作者:張凱慶 */

toEncode() 接收一個字串 str參數 (parameter) ,也回傳一個新字串 resultstr 就是要編碼的字串,而 result 則是編碼過的字串

進行編碼轉換的迴圈

# 利用迴圈走完參數字串的所有字元
for c in str:
  # 判斷該字元是否為英文小寫字母
  # 若是英文小寫字母就進行編碼轉換
  c1 = ord(c) >= 97
  c2 = ord(c) <= 122
  if c1 and c2:
    m = ord(c) - 97
    result += self.code[m]
  else:
    result += c

這裡用 for 迴圈逐一取得 str 中每一個元素,也就是單一字元的子字串,然後判斷那一個字元是否是英文小寫字母,如果是就將該字元的 Unicode 編碼值減去 97 ,依此當密碼表的索引值,取得 code 中該索引值的字元附加到 result 的最後。

測試部分也加進了準備編碼的字串,然後印出編碼結果

# 測試部分
if __name__ == '__main__':
  e = Encrypt()
  print()
  print(e.getcode())
  s1 = "There is no spoon."
  print("Input : " + s1)
  s2 = e.toEncode(s1)
  print("Encode: " + s2)
  print()

執行結果如下

$ python encrypt06.py
 
pyhqzirajsbktcludmvenwfoxg
Input : There is no spoon.
Encode: Tazmz jv cl vullc.
 
$

接下來,我們繼續加入解碼的功能吧!

中英文術語對照
編碼encoding
迴圈loop
參數parameter
字串string
重點整理
1. 轉換表格利用串列來儲存,每個元素都是長度為 1 的英文字母字串,可用索引值存取元素值。
2. 編碼時利用迴圈依序取得要編碼字串的所有字元,先判斷是否為英文小寫字母,如果是英文小寫字母就進行編碼,如果不是就直接把該字元附加到暫存變數的最後。
問題與討論
1. 要怎麼判斷一個字元是英文小寫字母或大寫字母?
2. 為什麼可以用對照表格的方式進行轉換?
練習
1. 承接上一個單元的猜數字遊戲,將新程式寫在 exercise1801.py 中,在遊戲迴圈中利用內建函數 len() 檢查使用者輸入的長度,若是長度不等於 4 就印出提示訊息進行下一輪。
2. 承上題,將答案 answer 改成串列,並以 "0""9" 十個字串當元素,用標準模組庫中 randomshuffle() 攪亂順序後取得前四個元素當遊戲答案。

相關教學影片

上一頁 單元 17 - 修正後的數學公式
回 Python 入門指南首頁
下一頁 單元 19 - 解碼
回 Python 教材首頁
回程式語言教材首頁