6.程式設計方法學
一、例項13:體育競技分析
1.1 問題分析
體育競技分析
- 需求:毫釐是多少?如何科學分析體育競技比賽?
- 輸入:球員的水平
- 輸出:可預測的比賽成績
體育競技分析:模擬N場比賽
- 計算思維:抽象 + 自動化
- 模擬:抽象比賽過程 + 自動化執行N場比賽
- 當N越大時,比賽結果分析會越科學
比賽規則
- 雙人擊球比賽:A & B,回合制,5局3勝
- 開始時一方先發球,直至判分,接下來勝者發球
- 球員只能在發球局得分,15分勝一局
1.2 自頂向下和自底向上
自頂向下(設計): 解決複雜問題的有效方法
將一個總問題表達為若干個小問題組成的形式,使用同樣方法進一步分解小問題,直至小問題可以用計算機簡單明瞭的解決。
自底向上(執行): 逐步組建複雜系統的有效測試方法
分單元測試,逐步組裝,按照自頂向下相反的路徑操作,直至系統各部分以組裝的思路都經過測試和驗證。
1.3 "體育競技分析"例項講解
程式總體框架及步驟
步驟1:列印程式的介紹性資訊。 #printInfo()
步驟2:獲得程式執行引數:proA, proB, n。 #printInfo()
步驟3:利用球員A和B的能力值,模擬n局比賽。 #simNGames()
步驟4:輸出球員A和B獲勝比賽的場次及概率。 #printSummary()
- 第一階段:程式總體框架及步驟
def main(): printIntro() probA,proB,n=getInputs() winsA,winsB=simNGames(n,proA,proB) printSummary(winsA,winsB) def printIntro(): print("這個程式模擬兩個選手A和B的某種競技比賽") print("程式執行需要A和B的能力值(以0到1之間的小樹表示)") def getInputs(): a = eval(input("請輸入選手A的能力值(0-1):")) b = eval(input("請輸入選手B的能力值(0-1):")) n = eval(input("模擬比賽的場次:")) return a, b, n def printSummary(winsA, winsB): n = winsA + winsB print("競技分析開始,共模擬{}場比賽".format(n)) print("選手A獲勝{}場比賽,佔比{:0.1%}".format(winsA, winsA / n)) print("選手B獲勝{}場比賽,佔比{:0.1%}".format(winsB, winsB / n))
- 第二階段:步驟3 模擬N局比賽
def simNGames(n, probA, probB):
winsA, winsB = 0, 0
for i in range(n):
scoreA, scoreB = simOneGame(probA, probB)
if scoreA > scoreB:
winsA += 1
else:
winsB += 1
return winsA, winsB
- 第三階段:根據分數判斷局的結束
def simOneGame(probA, probB):
scoreA, scoreB = 0, 0
serving = "A"
while not gameOver(scoreA, scoreB):
if serving == "A":
if random() < probA:
scoreA += 1
else:
serving = "B"
else:
if random() < probB:
scoreB += 1
else:
serving = "B"
return scoreA, scoreB
def gameOver(a, b):
return a == 15 or b == 15
1.4 舉一反三
理解自頂向下和自底向上
- 理解自頂向下的設計思維:分而治之
- 理解自底向上的執行思維:模組化整合
- 自頂向下是“系統”思維的簡化
應用問題的擴充套件
- 擴充套件比賽引數,增加對更多能力對比情況的判斷
- 擴充套件比賽設計,增加對真實比賽結果的預測
- 擴充套件分析邏輯,反向推理,用勝率推算能力?
1.5 完整程式碼
from random import random
def printIntro():
print("這個程式模擬兩個選手A和B的某種競技比賽")
print("程式執行需要A和B的能力值(以0到1之間的小樹表示)")
def getInputs():
a = eval(input("請輸入選手A的能力值(0-1):"))
b = eval(input("請輸入選手B的能力值(0-1):"))
n = eval(input("模擬比賽的場次:"))
return a, b, n
def printSummary(winsA, winsB):
n = winsA + winsB
print("競技分析開始,共模擬{}場比賽".format(n))
print("選手A獲勝{}場比賽,佔比{:0.1%}".format(winsA, winsA / n))
print("選手B獲勝{}場比賽,佔比{:0.1%}".format(winsB, winsB / n))
def simNGames(n, probA, probB):
winsA, winsB = 0, 0
for i in range(n):
scoreA, scoreB = simOneGame(probA, probB)
if scoreA > scoreB:
winsA += 1
else:
winsB += 1
return winsA, winsB
def simOneGame(probA, probB):
scoreA, scoreB = 0, 0
serving = "A"
while not gameOver(scoreA, scoreB):
if serving == "A":
if random() < probA:
scoreA += 1
else:
serving = "B"
else:
if random() < probB:
scoreB += 1
else:
serving = "B"
return scoreA, scoreB
def gameOver(a, b):
return a == 15 or b == 15
def main():
printIntro()
probA, probB, n = getInputs()
winsA, winsB = simNGames(n, probA, probB)
printSummary(winsA, winsB)
main()
二、Python程式設計思維
- 計算思維與程式設計
- 計算生態與Python語言
- 使用者體驗與軟體產品
- 基本的程式設計模式
2.1 計算思維與程式設計
-
計算思維:(Computational Thinking):計算思維是基於計算機的思維方式
第3種人類思維特徵
- 邏輯思維:推理和演繹,數學為代表,A->B B->C A->C
- 實證思維:實驗和驗證,物理為代表,引力波<-實驗
- 計算思維:設計和構造,計算機為代表,漢諾塔遞迴
抽象和自動化
抽象問題的計算過程,利用計算機自動化求解
- 計算思維基於計算機強大的算力及海量資料
- 抽象計算過程,關注設計和構造,而非因果
- 以計算機程式設計為實現的主要手段
- 計算思維與程式設計
程式設計是將計算思維變成現實的手段
2.2 計算生態與Python語言
從開源運動說起…
- 自由軟體時代到來
- 1983, Richard Stallman啟動GNU專案
- 1989, GNU通用許可協議誕生
- 開源生態逐步建立
- 1991, Linus Torvalds釋出了Linux核心
- 1998, 網景瀏覽器開源,產生了Mozilla
開源思想深入演化和發展,形成了計算生態
計算生態以開源專案為組織形式,充分利用“共識原則”和“社會利他”組織人員,
在競爭發展、相互依存和迅速更迭中完成資訊科技的更新換代,形成了技術的自我演化路徑
沒有頂層設計、以功能為單位、具備三個特點
- 競爭發展
- 相互依存
- 迅速更迭
計算生態與Python語言
-
以開源專案為代表的大量第三方庫
Python語言提供 >13萬個第三方庫
-
庫的建設經過野蠻生長和自然選擇
同一個功能,Python語言2個以上第三方庫
-
庫之間相互關聯使用,依存發展
Python庫間廣泛聯絡,逐級封裝
-
社群龐大,新技術更迭迅速
AlphaGo深度學習演算法採用Python語言開源
API != 生態
計算生態的價值
創新:跟隨創新、整合創新、原始創新
- 加速科技類應用創新的重要支撐
- 發展科技產品商業價值的重要模式
- 國家科技體系安全和穩固的基礎
計算生態的運用
刀耕火種 -> 站在巨人的肩膀上
- 程式設計的起點不是演算法而是系統
- 程式設計如同搭積木,利用計算生態為主要模式
- 程式設計的目標是快速解決問題
計算生態
2.3 使用者體驗與軟體產品
-
使用者體驗
實現功能 -> 關注體驗
- 使用者體驗指使用者對產品建立的主觀感受和認識
- 關心功能實現,更要關心使用者體驗,才能做出好產品
- 程式設計只是手段,不是目的,程式最終為人類服務
-
提高使用者體驗的方法
方法1:進度展示
- 如果程式需要計算時間,可能產生等待,請增加進度展示
- 如果程式有若干步驟,需要提示使用者,請增加進度展示
- 如果程式可能存在大量次數的迴圈,請增加進度展示
方法2:異常處理
- 當獲得使用者輸入,對合規性需要檢查,需要異常處理
- 當讀寫檔案時,對結果進行判斷,需要異常處理
- 當進行輸入輸出時,對運算結果進行判斷,需要異常處理
其他類方法
- 列印輸出:特定位置,輸出程式執行的過程資訊
- 日誌檔案:對程式異常及使用者使用進行定期記錄
- 幫助資訊:給使用者多種方式提供幫助資訊
-
軟體程式 -> 軟體產品
使用者體驗是程式到產品的關鍵環節
2.4 基本的程式設計模式
-
從IPO開始…
- I:Input 輸入,程式的輸入
- P:Process 處理,程式的主要邏輯
- O:Output 輸出,程式的輸出
- 確定IPO:明確計算部分及功能邊界
- 編寫程式:將計算求解的設計變成現實
- 除錯程式:確保程式按照正確邏輯能夠正確執行
-
自頂向下設計
- I:Input 輸入,程式的輸入
- P:Process 處理,程式的主要邏輯
- O:Output 輸出,程式的輸出
-
模組化設計
- 通過函式或物件封裝將程式劃分為模組及模組間的表達
- 具體包括:主程式、子程式和子程式間關係
- 分而治之:一種分而治之、分層抽象、體系化的設計思想
- 緊耦合:兩個部分之間交流很多,無法獨立存在
- 鬆耦合:兩個部分之間交流較少,可以獨立存在
- 模組內部緊耦合、模組之間鬆耦合
-
配置化設計
- 引擎+配置:程式執行和配置分離,將可選引數配置化
- 將程式開發變成配置檔案編寫,擴充套件功能而不修改程式
- 關鍵在於介面設計,清晰明瞭、靈活可擴充套件
2.5 應用開發的四個步驟
-
1 產品定義:對應用需求充分理解和明確定義
產品定義,而不僅是功能定義,要考慮商業模式
-
2 系統架構:以系統方式思考產品的技術實現
系統架構,關注資料流、模組化、體系架構
-
3 設計與實現:結合架構完成關鍵設計及系統實現
結合可擴充套件性、靈活性等進行設計優化
-
4 使用者體驗:從使用者角度思考應用效果
使用者至上,體驗優先,以使用者為中心
三、Python第三方庫安裝
- 看見更大的Python世界
- 第三方庫的pip安裝方法
- 第三方庫的整合安裝方法
- 第三方庫的檔案安裝方法
3.1 看見更大的Python世界
3.1.1 Python社群
- PyPI: Python Package Index
- PSF維護的展示全球Python計算生態的主站
- 學會檢索並利用PyPI,找到合適的第三方庫開發程式
三種方法
- 方法1(主要方法): 使用pip命令
- 方法2: 整合安裝方法
- 方法3: 檔案安裝方法
3.2 第三方庫的pip安裝方法
#安裝指定的第三方庫
pip install <第三方庫名>
#使用-U標籤更新已安裝的指定第三方庫
pip install –U <第三方庫名>
#解除安裝指定的第三方庫
pip uninstall <第三方庫名>
#下載但不安裝指定的第三方庫
pip download <第三方庫名>
#列出某個指定第三方庫的詳細資訊
pip show <第三方庫名>
#根據關鍵詞在名稱和介紹中搜索第三方庫
pip search <關鍵詞>
#列出當前系統已經安裝的第三方庫
pip list
主要方法,適合99%以上情況
- 適合Windows、Mac和Linux等作業系統
- 未來獲取第三方庫的方式,目前的主要方式
- 適合99%以上情況,需要聯網安裝
3.3 第三方庫的整合安裝方法
整合安裝:結合特定Python開發工具的批量安裝
- 支援近800個第三方庫
- 包含多個主流工具
- 適合資料計算領域開發
3.4 第三方庫的檔案安裝方法
為什麼有些第三方庫用pip可以下載,但無法安裝?
- 某些第三方庫pip下載後,需要編譯再安裝
- 如果作業系統沒有編譯環境,則能下載但不能安裝
例項:安裝wordcloud庫
- 步驟1:在UCI頁面上搜索wordcloud
- 步驟2:下載對應版本的檔案
- 步驟3:使用pip install <檔名>安裝