[python] [VI coding] 第四章 案例研究:介面設計 - 教學區

[python] [VI coding] 第四章 案例研究:介面設計

特種兵

特種兵圖像(預設)

2020-08-21 12:21:58

From:211.23.21.202

第四章 案例研究:介面設計

4-1 結合開發環境

目前我們每次在檔案中寫完程式都必須進指令列(command line)下執行程式,現在我們要把 notepad++ 跟 python 直譯器結合在一起。

也就是在 notepad++ 寫完程式就可以按一個快速鍵來執行程式,馬上看到程式執行結果,這有助於我們修改程式並大大增加開發程式的效率。

  1. 開啟 notepad++
  2. 按 F5 呼叫執行視窗
  3. 貼上 cmd /k cd /D "$(CURRENT_DIRECTORY)" & python "$(FILE_NAME)" & pause & exit
  4. 按 tab 到儲存並按 enter
  5. 在設定快捷鍵視窗核取 CTRL
  6. 使用 tab 鍵到下拉式方塊,按下方向鍵選擇 F6
  7. 按 tab 到編輯區輸入一個名稱,如: python
  8. 按 tab 到 確認 並按 enter
  9. 按 esc 鍵離開執行視窗
  10. 用 notepad++ 開啟副檔名為 .py 的檔案,按 ctrl+F6 確認是否有執行結果

4-2 安裝 pip

pip 是一個可以幫 python 安裝外部模組的程式,安裝以後,就可以像我們上一個章節描述的那樣載入模組並使用模組內的函數。

使用 pip 安裝模組的過程,可以想成是把那些模組的程式碼從網路上下載回來放在 python 可以搜尋到的路徑當中,提供程式去調用他們。

我們先來確認目前 python 有沒有安裝 pip 了:

  1. 按 win + r 開啟執行列
  2. 輸入 cmd 按 enter 進入 windows 命令列視窗
  3. 輸入 cd\python376\Scripts 按 enter 切換到該資料夾下。
    c:\python376 是我的 python 安裝路徑,預設的有可能是 c:\Users\administrator\AppData\Local\Programs\Python\Python37 而 administrator 是我的電腦使用者帳號。
  4. 輸入 pip 並按 enter 確認是否有該程式

往上看,如果沒有正確的執行結果,就在該資料夾下進行安裝:

  1. 輸入 easy_install pip 按 enter

建議將上面提到的 python Scripts 的絕對路徑也加入到系統 path 當中,以後要使用 pip 安裝程式就不用進到那麼深的資料夾了。

輸入 pip install 模組名稱 可以安裝模組,如果你想移除與更新模組。輸入 pip 按 enter 可以看到指令操作說明。

而輸入以下指令可以更新 pip 程式:

> python -m pip install --upgrade pip
Successfully installed pip-19.0.2

4-3 畫圖

讓我們練習寫三個函數來畫簡單的點字圖形或表格。

例如畫出 L 形、 H 形、方形還是表格的外框也可以。

讓我們來歸納需要的函數條件:

  1. 需要一個函數負責畫縱向的圖形
  2. 需要一個函數負責畫橫向的圖形
  3. 需要一個函數負責畫四個轉角的圖形
  4. 畫縱向與橫向的函數應該要有兩個參數,分別是圖形的符號與重複的次數
  5. 畫轉角的圖形只要一個轉角符號作為參數即可

點字的圖形符號整理如下,如果了解點字表格的話應該會很有感:

  1. 左上角 6
  2. 左下角 h
  3. 右上角 4
  4. 右下角 j
  5. 橫線 3
  6. 左直線 l
  7. 右直線 _
  8. 右上左下斜線 /
  9. 左上右下斜線 *
  10. 中間線的左交叉點 r
  11. 中間線的右交叉點 w

現在我們假定要畫一個 L 形,所以可能會這樣執行函數:

v('l', 3)
corner('h')
h('3', 2)

然後會畫出一個 L 形,像這樣:

l
l
l
h33

請完成這三個函數,並測試上面的執行方式是否真能畫出這樣的圖形。

自己試著利用這些函數畫一個正方形看看。

還可以畫出什麼圖形。

4-4 重複執行

重複的工作我們希望程式可以自動完成,它們做起來往往比人更可靠。

像上面的繪圖,我們想畫一條長 10 格的橫線會這樣寫:

h('3', 10)

事實上我們可以用 for 敘述讓程式更簡潔,以下是 python 的 for 迴圈範例:

for i in range(4):
	print('Hello!')

你會看到如下結果:

Hello!
Hello!
Hello!
Hello!

這是 for 迴圈的最簡單用法,有了迴圈,我們可以把上面的繪圖函數改寫成迴圈的版本。

或者利用迴圈來畫圖,而不是手動一直執行函數做相同的動作。

for 迴圈的寫法很像函數的定義,定義區塊需要縮排,使用冒號作為標題與定義的分隔符號,

i 是一個變數,當然不一定要使用這個名字。range 是一個內建函數,裡面放置你想要的執行次數。

i 會從 0 開始,每一圈增加 1 直到 range 裡的數值減 1 為止。

以上例來說就是 0, 1, 2, 3 共 4 圈。

我們會慢慢發現迴圈的好處,它有更多的應用情境。

4-5 畫星星

我們現在利用 for 迴圈來畫星星圖,寫一個函數名為 star 裡面有一個數字參數,它可以幫我們畫出星星圖,像這樣:

star(3)
*
**
***

star(5)
*
**
***
****
*****

如果你完成了,接下來挑戰進階版的 superStar() 函數

superStar(3)
*
**
***
**
*

最後是畫出三角形的星星圖 triangle() 函數

triangle(4)
   *
  ***
 ***** 
*******

4-6 封裝

在函數中包裝一段程式碼稱為封裝,好處是重新使用程式碼只需調用一次函數會更簡潔。

也比單純的手動複製、貼上好得多,封裝在函數內也可以變成一個模組讓其他程式導入並調用。

例如我們寫了一個名為 square 的函數,裡面調用了其他繪圖的函數實現了畫出正方形的功能,這就是函數的封裝概念。

4-7 介面

這邊的介面是指函數的設計而言,一個函數的功能、參數與回傳值這些訊息就是函數的介面設計。

一個良好的函數是避免做不相干的事情,簡而言之就是一個函數做一件事情,盡量把函數功能拆分清楚。

這樣在不同的情境下,這些函數才有重複被利用的價值。

例如你設計了一個畫正方形的函數,裡面順便把畫對角線的功能加進去了。

這樣的設計在這個需要畫對角線的應用當中或許很方便。但如果下次我想畫的是兩個正方形構成的長方形而不需要畫對角線呢?

所以比較好的函數介面設計是畫正方形一個函數,畫五角形一個函數,畫對角線一個函數。

這樣下次不管畫什麼形,如果還要加上對角線,只要選擇畫什麼形的函數再加上去調用畫對角線的函數就完成了。

4-8 泛形

目前先不討論它,我們先重在實做的部分,關於這部分的討論可以參考講義後面的 參考書目

4-9 重構

重新整理一個程式以改進函數介面和促進程式碼重複利用的這個過程,被稱為重構。

例如你設計了一個畫正方形的函數,但你現在想要畫一個菱形。

菱形和正方形可能有一些特性是相同的,但還是有些不同,我們通常會拿寫好的畫正方形函數來修改成畫菱形的函數。

這樣會更省事,這就是重構的現象。

在一開始撰寫程式時我們往往無法考慮到那麼完全,經常是有需求時再針對已經有的程式依需求做一些修改,

重構的過程會讓我們學到更多,以後隨著經驗的累積,我們在規劃函數或程式上會更靈活、通用且完整。

一開始可能會是想到什麼寫什麼,最後雖然完成功能,但其實程式碼不好閱讀且冗長,

再回來看之前的程式,如果你可以重構它,就表示你有在成長,功力也隨之提升。

4-10 開發計劃

規劃好程式再進行撰寫是很重要的。在前面我們練習怎麼思考並找出相同點與不同點來完成程式或函數。

我們把這些過程歸納一下:

  1. 一開始寫一個沒有函數的程式,先把功能完成
  2. 程式的功能測試正常後試著找出一些相同的程式碼,將它提取出來改寫成函數
  3. 改寫函數後讓他的介面設計乾淨,讓原本的程式可以順利調用它
  4. 調整你的函數設計,避免重複的程式碼,讓整個輸出與輸入更邏輯化,並讓函數更有應用性。
  5. 有機會時改進程式或函數,例如在多個地方有重複的程式碼,應該考慮分解到合適的通用函數中

至少透過上述的練習,可以讓我們的整個程式更模組化,邏輯性也更強,

簡單的說就是更專業,看起來也更像程式。

4-11 說明字串(docstring)

這個說明字串通常位在函數定義的一開始,主要是用於解釋函數的用途。

也可以說就是函數一開始的區塊註解。

我們之前提過單行註解,現在說的是區塊註解,就是有好幾行的註解,如果每行都要打 # (井號) 有點麻煩。

它很重要,使用三個引號包起來,也稱為多行註解。

簡要的說明函數用途,參數的意義與形態,讓程式設計師快速了解是不是要調用或改寫這個函數。

def errorDialog(message, this_text, caption):
	''' 顯示對話框的設計 適用整個程式需要彈出訊息時
	message 在視窗中顯示的訊息文字
	this_text 當該視窗關閉後會將焦點移到這個元件上
	caption 該對話框的標題文字 '''

除錯

介面是函數與呼叫者之間的契約與橋樑。

呼叫者根據介面的描述提供正確的參數,而函數根據呼叫者的需求完成功能。

就像剛才的 errorDialog 函數,它有三個參數:

  1. message 是一個字串
  2. this_text 是一個元件
  3. caption 是一個字串

功能都已經在註解中說明,當然也可以把形態也寫進去。

以上這些要求稱為 前置條件,因為他必須在函數執行前確保成立。

相對的,另外一個稱為 後置條件,也就是函數結束前帶來的效果,例如畫線、畫圖、移動或任何改變等行為。

因為前置條件由呼叫者提供,當前置條件不正確時產生的錯誤需由調用函數的人負責。

反之,如果呼叫者確實依循函數介面提供符合條件的參數,但結果不如預期時則函數開發者必須負責。

接著,舉兩個在撰寫程式縮排時容易遇到的典型錯誤:

# 敘述屬於 for 迴圈內,該縮排而未縮排
for i in 'hello':
print(i)
# IndentationError: expected an indented block

# 敘述應該在同一層級區塊,不該縮排卻縮排
s = 'hello'
	print(s)
# IndentationError: unexpected indent

動動腦

架構程式的一個方式,撰寫虛擬碼,以 猜三位數 為例,讓我們寫寫看。

設定答案
進入迴圈:
	讓使用者輸入所猜的數字
	if 使用者猜太大:
		提示使用者要猜小一點
	elif 使用者猜太小:
		提示使用者猜大一點
	else: 
		提示使用者猜對了
		離開迴圈

練習

第1題 檔名 4-1.py

構建出一套可以用鍵盤符號畫出表格的函數。

整理符號如下:

  1. 橫線 -
  2. 直線 |
  3. 十字交叉 +

我們只是做練習,所以圖形沒那麼完美也無所謂,例如橫線跟直線的交叉點會有漏洞。

寫一支程式用這些圖形來畫表格或類似的圖案。

第2題 檔名 4-2.py

使用 for 迴圈改寫第二章的習題,求 1 到 10 的和,把它寫成函數,帶入 n 可以算出 1 到 n 的和。

參考資料

關於 python 的泛型討論

最後更新:2020-09-28 09:15:23

From: 211.23.21.202

By: 特種兵