學習程式設計第一步 零基礎上手Python開發

qinghuawenkang發表於2018-10-23
學習程式設計第一步
零基礎上手 Python 開發



[英] 羅伯 • 麥爾斯(Rob Miles)

郭俊鳳


北 京
Authorized translation from the English language edition, entitled BEGIN TO CODE WITH
PYTHON, 1st Edition, 9781509304523 by MILES, ROB, published by Pearson Education, Inc,
publishing as Microsoft Press, Copyright © 2018.
All rights reserved. No part of this book may be reproduced or transmitted in any form or by any
means, electronic or mechanical, including photocopying, recording or by any information storage
retrieval system, without permission from Pearson Education, Inc.CHINESE SIMPLIFIED language
edition published by TSINGHUA UNIVERSITY PRESS LIMITED, Copyright © 2018.
本書封面貼有清華大學出版社防偽標籤,無標籤者不得銷售。
版權所有,侵權必究。侵權舉報電話:
010-62782989 13701121 933
圖書在版編目 (CIP) 資料
學習程式設計第一步 零基礎上手 Python 開發 / (英)羅伯•麥爾斯(Rob Miles) 著;曹瑜,
郭俊鳳 譯. —北京:清華大學出版社, 2018
書名原文: Begin to Code with Python
ISBN 978-7-302-50249-4
Ⅰ. ①學… Ⅱ. ①羅… ②曹… ③郭… Ⅲ. ①軟體工具-程式設計 Ⅳ. ①TP311.561
中國版本圖書館 CIP 資料核字(2018)第 103231 號
責任編輯:王 軍 於 平
封面設計: 牛豔敏
版式設計: 思創景點
責任校對: 曹 陽
責任印製: 劉海龍

出版發行: 清華大學出版社
網 址: ,
地 址: 北京清華大學學研大廈 A 座
郵 編: 100 084
社 總 機: 010-62770175 郵 購: 010-62786544


投稿與讀者服務: 010-62776969, c-service@tup.tsinghua.edu.cn

質 量 反 饋: 010-62772015, zhiliang@tup.tsinghua.edu.cn
印 裝 者: 三河市君旺印務有限公司





銷: 全國新華書店



本: 170mm×240mm 張: 31.25 數: 630 千字


版 次: 2018 年 6 月第 1 版 印 次: 2018 年 6 月第 1 次印刷
印 數: 1~4000
定 價: 79.80 元
產品編號: 078950-01

譯 者 序
Python 是一種解釋型、物件導向、動態資料型別的高階程式設計語言。透過
Python 程式設計,我們能解決現實生活中的很多問題。自 1991 年問世以來, Python
日益流行,現已成為多個國家計算機教學中的首選入門程式語言之一。 Python 雖
然簡單,其設計卻十分嚴謹。 Python 可能沒有 C 或 C++這類編譯型語言執行速度
那麼快,但是 C 和 C++需要你無時無刻地關注資料型別、記憶體溢位、邊界檢查等
問題; Python 就像一個貼心的僕人,私下為你處理好這些,而你可將全部心思放
在程式的設計邏輯上。
本書是一本程式設計啟蒙書籍,將為你的程式設計之旅指明方向,指引你朝著正確的、
有用的目標前進。本書共分三部分。第I部分介紹如何安裝和使用程式設計工具,講
述 Python 程式語言的基本元素。第 II 部分描述如何利用 Python 程式語言的特點
構建複雜的應用程式;指導你設計、測試 Python 應用程式,併為程式編寫文件。
第 III 部分介紹如何使用軟體庫在圖形使用者介面中建立應用程式, 如何在網路應用
中將 Python 程式用作客戶端和伺服器。最後建立充滿魅力的遊戲。
即使你沒有程式設計經驗,也可在本書的指導下編寫出解決實際問題的軟體。本
書完全顛覆了程式設計入門書籍,緊跟時代,為當今的程式設計新手提供深入的講解,令
其他書籍望塵莫及。本書編排新穎,從“程式碼分析”“易錯之處” “動手練習”
到“專家點津”,無不令人耳目一新。無論你是初出茅廬的新手,還是經驗豐富的
程式設計人員,本書都將賦予你能量、激動和快樂!當你看到其他使用者樂於使用你寫
的程式做一些有用的事情時,你的內心將是十分甜蜜的。
在這裡要感謝清華大學出版社的編輯們,他們為本書的翻譯投入了巨大熱情
並付出了很多心血。沒有他們的幫助和鼓勵,本書不可能順利付梓。翻譯過程中,
譯者力求翻譯表達傳神,但是鑑於水平有限,難免出現錯誤和失誤,請不吝指正。
感激不盡!
本書主要內容由曹瑜、郭俊鳳翻譯,參與本次翻譯的還有陳妍、何美英、陳
宏波、熊曉磊、管兆昶、潘洪榮、曹漢鳴、高娟妮、王 燕、謝李君、李珍珍、王
璐、王華健、柳松洋、曹曉松、陳彬、洪妍、劉 芸、邱培強、高維傑、張素英、
顏靈佳、方 峻、顧永湘、孔祥亮,在此一併表示感謝!
最後,希望讀者在閱讀過程中領略到 Python 語言之美!

作 者 簡 介
Rob Miles 在英國赫爾大學講授程式設計課程的年限
超過 30 年。他是一位 Microsoft MVP,對編寫程式和
創造新事物充滿熱情。即使在空閒時間,也不忘繼續編
寫程式碼。他喜歡編寫程式碼,然後執行這些程式碼,看看會
有什麼結果。他認為程式設計最富有創意,讓你可以一探究
竟。他相信,程式設計可以構築未來。
Rob 自詡為一個段子手, 但旁人卻從未親耳聽到他
講的笑話。如果你想進一步接觸和了解 Rob,則可訪問
他的部落格 ,或透過@RobMiles 在 Twitter 上找到他。

前 言
要對事物一探究竟,程式設計是最富有創意的活動。為什麼這樣講呢?如果你學
習繪畫,你可以繪出作品。如果你學習拉小提琴,你能演奏出音樂。但如果你學
習程式設計,那將是一番新體驗(當然,如果願意,也可編寫程式碼來繪畫或演奏)。一
旦踏上程式設計之旅,你去往哪裡將再無限制。新的裝置、技術和市場層出不窮,你
的程式設計技能總有用武之地。
本書是一本程式設計啟蒙書籍,將為你的程式設計之旅指明方向,指引你朝著正確的、
有用的目標前進。透過學習本書,你將掌握程式設計技能,並編寫出有用的程式。
不過,在出發前,先要宣告幾個注意點。就像遊獵時,導遊會向你介紹獅子、
老虎和鱷魚,我要向你透露一點,我們的旅程並非是一帆風順的。對於如何解決
問題,程式設計人員必須稍微轉變一下思路,原因是計算機的工作方式與人類不同。
人類可以小心翼翼地完成複雜事情,計算機可極快地完成簡單工作。程式設計人員的
職責是利用計算機的簡單能力去解決複雜問題;這就是我們要學的內容。程式設計人
員取得成功的關鍵與其他很多職業是類似的。要成為一位聞名世界的小提琴家,
就必須做大量的練習。程式設計同樣如此,只有耗費大量時間處理程式,才能掌握編
程技能。當你看到其他使用者樂於使用你編寫的程式做一些有用的事情時,你的內
心將是十分甜蜜的。
本書的編排方式
本書共分三部分。後一部分建立在前一部分的基礎上,以便循序漸進地引導
你成為一名成功的程式設計人員。首先講述基本程式設計指令,這些指令將告知計算機如
何完成任務。最後將講解如何構建專業軟體。
第 I 部分 程式設計基礎知識
第I部分介紹如何安裝和使用程式設計工具,講述 Python 程式語言的基本元素。
你將學會編寫第一個程式,領會所有程式的底層構建方式。你將瞭解 Python 在編
程語言中的地位和重要性。
第 II 部分 高階程式設計
第 II 部分描述如何利用 Python 程式語言的特點來構建複雜的應用程式。從中
你將瞭解到,可將大程式分解為多個較小的元素,也可根據要解決的具體問題創
建自定義資料型別;你將能設計、測試 Python 應用程式,併為程式編寫文件。

VI 學習程式設計第一步 零基礎上手 Python 開發
第 III 部分 Python 實戰
學會如何自己編寫程式後,下一步學習如何使用其他人編寫的程式碼。 Python
的一個重要優勢在於: Python 使用者可使用大量的軟體庫。第 III 部分將介紹其中的
很多軟體庫,並講述如何使用這些庫在圖形使用者介面中建立應用程式,如何在網
絡應用中將 Python 程式用作客戶端和伺服器。最後將建立充滿魅力的遊戲。
可將本書第 III 部分作為一個可下載的文件,你可在桌面上開啟該文件,體驗
所演示的程式,並自行建立應用程式。
學習本書的方式
每一章都講解有關 Python 程式設計的新知識,先講解如何做,然後指導你動手練
習並自行建立程式。在這本精心撰寫的書籍中,沒有哪一頁是多餘的。不過,你
也可根據自己的需要選學。
你可從頭到尾閱讀本書,這樣,你可慢慢消化更多知識,直至編寫能夠使用
的程式。就像騎腳踏車一樣,從做中學。為此,你必須投入時間,不斷練習。本
書將指導你掌握知識,使你信心百倍地著手程式設計;如果此前你的程式未能如期運
行,你也可從本書中尋找靈感。為此,本書納入了以下一些特殊段落。
動手練習
沒錯,從做中學效果最好。全書穿插多個“動手練習”,帶你親手練習程式設計
技能。每個“動手練習”都首先引入一個示例,然後列出一些你可以自己去嘗試
的步驟。建立的程式碼能在 Windows、 Mac OS 或 Linux 上執行。
程式碼分析
學習程式設計的一種絕佳方式是分析其他人編寫的程式碼,並分析其工作原理,有
時需要查明為什麼程式碼不能如期工作。本書包含 150 多個可供你分析的示例程式。
你將推理論證程式的行為、改正錯誤,並提供改進建議。
易錯之處
如果你此前從未聽說過程式會失敗,那麼在編寫你的第一個程式之後,你很
快將體驗到酸楚。為幫助你處理問題,本書新增了“易錯之處”特殊段落,以推
測你可能遇到的問題,並提出解決方案。例如,在介紹新知識點時,總會討論哪
些地方容易出錯;在討論新功能時,總是告訴你一些需要考慮的事項。
專家點津
我講授程式設計課程已 30 年有餘,也編寫過很多商業程式。我知道,開始時必須
掌握一些要點。“專家點津”預先為你呈現這些資訊,使你在學習過程中,可以
像專業開發人員那樣考慮問題。其中涵蓋的問題十分廣泛,從程式設計到工作態度,
再到哲理。強烈建議你閱讀領會這些觀點,這樣,在未來可節省大量時間!

前 言 VII
軟體和硬體要求
為練習本書中的程式,你需要配備一臺計算機,並安裝一些軟體。我恐怕沒
法給你提供計算機,但在第 1 章中,你可以瞭解到從何處獲得 Python 工具和 Visual
Studio Code 應用程式;開始建立更大型的應用程式時,這些都必不可少。
使用 PC 或膝上型電腦
可使用 Windows、 Mac OS 或 Linux 來建立和執行本書中的 Python 程式。對
PC 硬體的最低要求如下:
● 1GHz 或主頻更高的處理器,最好使用 Intel i5 或更高效能的處理器。
● 至少4GB記憶體,最好是8GB記憶體。
● 256GB硬體空間(完整安裝Python和Visual Studio Code將佔用約1GB的硬
盤空間)。
對於顯示卡沒有具體要求,但編寫程式時,更清晰的螢幕當然會好一些。
移動裝置
可在移動裝置或平板電腦上編寫和執行 Python 程式。 如果有一臺執行 iOS 的
Apple 裝置,建議你使用 Pythonista 應用。如果使用 Android 裝置,應使用 Pyonic
Python 3 直譯器。
使用 Raspberry Pi
如果手頭缺少資金,開始時可使用最廉價的 Raspberry Pi(執行 Raspbian 操作
系統),其中內建 Python 3.6 和 IDLE 開發環境。
原始碼下載
本書每一章都演示和解釋程式,以幫助你理解程式設計機理。你也可在這些程式
的基礎上自行編寫其他程式,可訪問 ,
或掃描本書封底的二維碼,下載本書的示例程式碼。
可按第 1 章的說明來安裝示例程式和程式碼。
致 謝
感謝 Laura Norman 給予我撰寫本書的機會,感謝 Dan Foster 和 Rick Kughen
對本書的整理和編輯,感謝 John Ray 富有建設性的精闢技術建議,感謝 Tracey
Croom、 Becky Winter 和 Rob Nance 的排版和加工。
最後感謝妻子 Mary 的支援,你為我沏好一杯又一杯清茶,還為我烘焙軟餅,
謝謝你的愛。

VIII 學習程式設計第一步 零基礎上手 Python 開發
勘誤、更新和相關支援
我們已經盡最大努力,確保本書的資訊正確無誤。可訪問
BegintoCodePython/errata 來獲得本書的更新資訊,其中包括已提交的勘誤和相關
的更正意見。
如果你發現了未在勘誤表中列出的其他錯誤,也可將其提供給以上網頁。
如果需要其他支援,可給 Microsoft Press Book Support 傳送電子郵件:
mspinput@microsoft.com。
請注意,上述地址不提供 Microsoft 軟體和硬體支援。如果需要獲得有關
Microsoft 軟體和硬體的幫助,可訪問 。
獲得 MTA 認證
MTA(Microsoft Certified Professional)計劃旨在使你獲得技術認證。透過
98-381 考試“Introduction to Programming Using Python”, 你將獲得 MTA 的 Python
編 程 認 證 , 可 通 過 以 下 網 址 了 解 考 試 詳 情 :
learning/exam-98-381.aspx。
為幫助你儘量透過學習本書獲得MTA認證,這裡將考點與本書素材一一對應
列出。注意,考點基於2017年10月公佈的考試大綱。
認證結構
將認證劃分為多個主題,每個主題都佔一定比例。你可以閱讀每個主題,並
找到與本書對應的素材。下面的表格列出了對應關係。
1) 使用資料型別和運算子執行操作(20%~25%)
該主題與以下幾章的關係最密切:第 4 章描述 Python 程式的資料處理要點,
以及如何操縱和儲存文字和數值;第 5 章介紹布林變數型別,講述如何操作邏輯
值;第 8 章描述如何儲存資料集合;第 9 章講述如何建立和儲存資料結構;第 11
章詳述 Python 程式中的集合。

考點 本書的對應章節
表示式求值,識別 Python 為每個變數指定
的資料型別。識別 str、 int、 float 和 bool 數
據型別
第 4 章: Python 中的變數
第 4 章:使用文字
第 4 章:使用數值
第 5 章:布林資料
第 5 章:布林表示式



前 言 IX
(續表)

考點 本書的對應章節
執行資料和資料型別操作。 將一種資料型別
轉換為另一種;構建資料結構;執行索引和
切片操作
第 4 章:將字串轉換為浮點值
第 4 章:在浮點數和整數之間轉換
第 4 章:實數和浮點數
第 8 章:列表和銷售金額跟蹤
第 9 章:使用類儲存聯絡人資訊
根據運算子的優先順序確定執行順序: 賦值運
算符(=)、比較運算子、邏輯運算子、算術
運算子、身份運算子(is)、成員運算子(in)
第 4 章:執行計算
第 9 章: Contact 物件和引用
第 11 章:集合和標記
選擇適當的運算子取得預期結果: 賦值運算
符、 比較運算子、 邏輯運算子、 算術運算子、
身份運算子(is)、成員運算子(in)
第 4 章:執行計算
第 9 章:布林表示式


2) 使用決策和迴圈控制流程(25%~30%)
該主題與以下幾章的關係最密切:第 5 章介紹 if 結構;第 6 章講述用於實現
Python 程式迴圈的 while 和 for 迴圈結構。

考點 本書的對應章節
構建和分析使用分支語句的程式碼段 第 5 章:布林資料
第 5 章: if 結構
if、 elif、 else、巢狀和複合條件表示式 第 5 章: if 結構
構建和分析執行迭代的程式碼段 第 6 章: while 結構
第 6 章: for 迴圈結構
while、 for、 break、 continue、 pass、巢狀的循
環以及包含複合條件表示式的迴圈
第 6 章: while 結構
第 6 章: for 迴圈結構
第 8 章:使用氣泡排序法


3) 執行輸入和輸出操作(20%~25%)
從第 3 章和第 4 章描述的第一個程式開始,本書穿插介紹如何使用控制檯輸
入和輸出函式。第 8 章簡要介紹在 Python 程式中使用檔案儲存,第 9 章進一步介
紹如何使用 Python pickle 庫將資料結構儲存在檔案中。第 10 章詳細介紹 Python
程式中的字串格式化工具。

考點 本書的對應章節
構建和分析執行檔案輸入和輸出操作的程式碼
段。理解 open、 close、 read、 write、 append、
check existence、 delete、 with 語句
第 8 章:在檔案中儲存資料
第 9 章:使用 pickle 將聯絡人資訊儲存到文
件中



X 學習程式設計第一步 零基礎上手 Python 開發
(續表)

考點 本書的對應章節
構建和分析執行控制檯輸入和輸出操作的代
碼段;包括從控制檯讀取、列印帶格式的文
本以及使用命令列引數
第 3 章:使用 print 函式獲取程式輸出
第 4 章:使用 input 函式讀取文字
第 10 章:設定 Python 字串格式


4) 程式碼的文件化和結構(15%~20%)
本書強調:程式碼的結構必須清晰,程式碼必須進行文件化。第 3 章簡要介紹
Python 註釋,第 5 章強調良好程式碼佈局的重要性。第 7 章講述透過 Python 函式完
善程式結構,並描述如何給函式新增文件,作為程式的自我說明。

考點 本書的對應章節
使用註釋和文件字串實現程式碼段的文件
化。使用縮排、空白、註釋和文件字串;
使用 pydoc 生成文件
第 3 章: Python 註釋
第 5 章:縮排文字可導致大問題
第 7 章:為函式新增幫助資訊
第 12 章:檢視程式文件
構建和分析包含函式定義的程式碼段:呼叫籤
名、預設值、 return、 def、 pass
第 7 章:函式的組成


5) 故障排除和錯誤處理(5%~10%)
第 3 章介紹 Python 程式碼中的語法錯誤。第 4 章描述資料處理中的執行時錯誤。
第 6 章和第 7 章討論應用程式開發環境中產生邏輯錯誤的原因和後果。第 6 章和
第 10 章講述 Python 程式如何丟擲和管理異常。第 12 章講述在 Python 程式測試
中使用單元測試。

考點 本書的對應章節
分析、檢測和糾正包含以下錯誤的程式碼段:
語法錯誤、邏輯錯誤、執行時錯誤
第 3 章:不完整的程式
第 4 章:輸入錯誤和測試
第 5 章:相等和浮點值
第 6 章:看似正確的迴圈出錯了
第 7 章:使用偵錯程式探究程式
第 12 章:程式測試
分析和構建用於處理異常的程式碼段: try、
except、 else、 finally、 raise
第 6 章:使用異常檢測無效編號輸入
第 10 章:丟擲異常指示錯誤


6) 使用模組和工具執行操作(1%~5%)
本書使用的很多 Python 模組都以 random 和 time 模組開頭。第 13 章使用
random 庫的函式來建立 random 工件,第 16 章的時間跟蹤應用程式使用 time 庫
的函式。

前 言 XI

考點 本書的對應章節
使用內建模組執行基本操作: math、 datetime、
io、 sys、 os、 os.path、 random
第 3 章: random 庫
第 3 章: time 庫
使用內建模組解決複雜計算問題: math、
datetime、 random
第 10 章: Time Tracker 中的會話跟蹤
第 16 章:生成工件


聯絡我們
Microsoft Press 將“讓讀者滿意”奉為至高無上的宗旨,你的反饋是我們最寶
貴的資產。請透過 tellpress 將你對本書的意見發給我們。
為節省時間,其中只有幾個簡短問題。你的回答將直接反饋到 Microsoft
Press(不需要提供個人資訊)。
提前謝謝你的反饋!
另外,你可透過 Twitter()與我們交流。

目 錄
第Ⅰ部分 程式設計基礎知識
第 1 章 開始使用 Python··············· 3
1.1 什麼是 Python····················· 3
1.1.1 Python 的起源 ················· 4
1.1.2 Python 版本 ····················· 4
1.2 打造使用 Python 的場所 ···· 5
1.2.1 獲取工具 ························· 5
1.2.2 Python(適用於
Windows PC) ···················
6
1.3 啟動 Python························· 8
1.4 本章小結 ····························11
第 2 章 Python 和程式設計 ················ 13
2.1 程式設計人員的工作 ················13
2.1.1 程式設計和規劃生日聚會··· 13
2.1.2 程式設計和問題 ·················· 14
2.1.3 程式設計人員要善於溝通··· 15
2.2 計算機用於處理資料·········16
2.2.1 機器、計算機和人······· 16
2.2.2 程式用於處理資料······· 18
2.2.3 Python 用於處理資料··· 19
2.3 資料和資訊 ························23
2.4 使用 Python 函式 ···············27
2.4.1 ord 函式························ 27
2.4.2 chr 函式························ 28
2.4.3 使用 bin 函式探索資料
儲存 ······························
29
2.5 本章小結 ····························30
第 3 章 Python 程式結構 ·············33
3.1 編寫首個 Python 程式 ·······33
3.1.1 使用 IDLE 執行 Python
程式·······························
33
3.1.2 使用 print 函式獲得程式
輸出·······························
37
3.2 使用 Python 庫···················42
3.2.1 random 庫······················ 42
3.2.2 time 庫··························· 45
3.3 Python 註釋························46
3.4 從桌面執行 Python············47
3.5 新增一些 snaps 函式··········48
3.5.1 新增 pygame 庫············· 48
3.5.2 snaps 函式 ····················· 49
3.6 本章小結····························52
第 4 章 使用變數 ·························55
4.1 Python 中的變數················55
4.2 使用文字····························59
4.2.1 標記字串的開始和
結束·······························
61
4.2.2 文字中的跳脫字元········ 62
4.2.3 使用 input 函式讀取
文字·······························
63
4.3 使用數值····························65
4.3.1 將字串轉換為整
型值·······························
65
4.3.2 整數和實數 ··················· 66
4.3.3 實數和浮點數 ··············· 67
4.3.4 將字串轉換為浮
點值·······························
71
XIV 學習程式設計第一步 零基礎上手 Python 開發
4.3.5 執行計算 ······················ 72
4.3.6 在浮點數和整數之間
轉換 ······························
73
4.4 snaps 函式 get_weather_
temp ····································75
4.5 本章小結 ····························76
第 5 章 在程式中制定決策 ·········· 79
5.1 布林資料 ····························79
5.1.1 建立布林變數 ·············· 79
5.1.2 布林表示式 ·················· 81
5.1.3 比較值 ·························· 83
5.1.4 布林運算 ······················ 86
5.2 if 結構 ································88
5.2.1 巢狀 if 條件·················· 95
5.2.2 使用邏輯 ······················ 96
5.3 使用決策建立應用程式·····96
5.3.1 設計使用者介面 ·············· 97
5.3.2 實現使用者介面 ·············· 98
5.3.3 測試使用者輸入 ·············· 99
5.3.4 完成程式 ······················ 99
5.4 匯入 snaps 庫 ···················100
5.5 本章小結 ··························103
第 6 章 使用迴圈執行重複
操作······························ 105
6.1 while 結構 ························105
6.1.1 使用 while 重複執行一
系列語句 ····················
105
6.1.2 處理無效的使用者輸入 ·· 109
6.1.3 使用異常檢查無效編號
輸入 ····························
112
6.1.4 異常和編號讀取········· 114
6.1.5 處理多個異常 ············ 115
6.1.6 跳出迴圈 ···················· 116
6.1.7 使用 continue 返回到迴圈
頂部 ····························
117
6.1.8 重複迴圈計數 ············ 118
6.2 for 迴圈結構 ····················120
6.3 使用 snaps 製作數字
鬧鐘··································123
6.4 本章小結··························124
第 7 章 使用函式簡化程式·········125
7.1 函式的組成······················125
7.1.1 使用引數給函式提供
資訊·····························
128
7.1.2 函式呼叫的返回值······ 135
7.2 構建可重用的函式 ··········141
7.2.1 建立文字輸入函式······ 141
7.2.2 為函式新增幫助資訊·· 142
7.2.3 建立數值輸入函式······ 144
7.2.4 將函式轉換為 Python
模組·····························
147
7.2.5 使用 IDLE 偵錯程式 ······ 148
7.3 本章小結··························153
第 8 章 儲存資料集合 ················155
8.1 列表和銷售金額跟蹤 ······155
8.1.1 單獨變數的侷限性······ 157
8.1.2 Python 中的列表 ········· 158
8.1.3 在列表中讀取值 ········· 160
8.1.4 使用 for 迴圈顯示
列表·····························
161
8.2 將程式重構為函式 ··········162
8.2.1 建立佔位函式 ············· 165
8.2.2 建立使用者選單 ············· 165
8.3 使用氣泡排序法 ··············167
8.3.1 使用測試資料初始化
列表·····························
167
8.3.2 按降序排序列表 ········· 168
8.3.3 按升序排序列表 ········· 172
8.3.4 查詢最大值和最
小值·····························
173
8.3.5 計算銷售總額和平均
銷售額·························
174
目 錄 XV
8.3.6 完成程式 ···················· 174
8.4 在檔案中儲存資料 ··········175
8.4.1 寫入檔案 ···················· 176
8.4.2 寫入銷售金額 ············ 179
8.4.3 從檔案讀取 ················ 180
8.4.4 讀取銷售金額 ············ 182
8.4.5 處理檔案錯誤 ············ 183
8.5 儲存資料表 ······················185
8.6 將列表用作查詢表 ··········188
8.7 元組··································189
8.8 本章小結 ··························191
第 II 部分 高階程式設計
第 9 章 使用類儲存資料············ 197
9.1 生成 Tiny Contacts
應用 ··································197
9.1.1 生成原型 ···················· 198
9.1.2 在不同的列表中儲存聯絡
人詳細資訊 ················
200
9.1.3 使用類儲存聯絡人詳細
資訊 ····························
202
9.1.4 在 Tiny Contacts 程式中
使用 Contact 類 ··········
205
9.1.5 編輯聯絡人資訊········· 207
9.1.6 使用 pickle 將聯絡人資訊
儲存到檔案中·············
215
9.1.7 使用 pickle 從檔案載入
聯絡人資訊 ················
217
9.1.8 給 Tiny Contacts 程式新增
save 和 load 函式········
218
9.1.9 設定類例項 ················ 219
9.2 字典··································223
9.2.1 字典管理 ···················· 225
9.2.2 從函式返回字典········· 225
9.2.3 使用字典儲存聯絡人
資訊 ····························
226
9.3 本章小結··························227
第 10 章 使用類建立活動物件 ···229
10.1 建立 Time Tracker··········229
10.1.1 為類新增資料
特性·························
230
10.1.2 建立聚合物件 ········· 231
10.1.3 為類建立方法
特性·························
232
10.1.4 為方法新增驗證
程式碼·························
234
10.1.5 防止資料特性受到
破壞·························
243
10.1.6 受保護的方法 ········· 246
10.2 建立類屬性 ····················246
10.3 擴充套件類設計 ····················250
10.4 類中的__str__方法········257
10.5 Time Tracker 中的法庭工作
時長跟蹤························260
10.5.1 Python map 函式 ····· 264
10.5.2 Python join 方法 ······ 269
10.6 使用 snaps 製作音樂······270
10.7 本章小結························273
第 11 章 設計物件導向的解決
方案·····························277
11.1 Fashion Shop 應用
程式································277
11.1.1 應用程式資料
設計 ·························
279
11.1.2 物件導向的設計······ 279
11.1.3 建立超類和子類······ 282
11.1.4 資料設計總結·········· 295
11.1.5 實現應用程式
行為 ························
302
11.1.6 將物件作為元件······ 305
11.2 建立 FashionShop
元件································306

XVI 學習程式設計第一步 零基礎上手 Python 開發
11.3 設計類 ····························314
11.4 Python 集合 ····················315
11.4.1 集合和標籤············· 318
11.4.2 集合與類層次結構的
對比 ························
321
11.5 本章小結 ························324
第 12 章 Python 應用程式········· 327
12.1 高階函式 ························327
12.1.1 函式引用 ················ 327
12.1.2 使用 lambda
表示式 ····················
332
12.1.3 迭代器函式和 yield
語句 ························
335
12.1.4 使用任意實引數量的
函式 ························
340
12.2 模組和包 ························343
12.2.1 Python 模組 ············ 343
12.2.2 給 BTCInput 新增
readme 函式············
343
12.2.3 將模組作為程式
執行 ························
344
12.2.4 檢測模組是否作為程式
執行 ························
344
12.2.5 建立 Python 包 ······· 345
12.2.6 匯入包中的模組····· 347
12.3 程式測試 ························350
12.3.1 Python assert 語句··· 351
12.3.2 Python unittest
模組 ························
352
12.3.3 建立測試 ················ 355
12.4 檢視程式文件 ················356
12.5 本章小結 ························361
第 III 部分 Python 實戰
第 13 章 Python 和圖形使用者
介面 ···························· 365
13.1 Visual Studio Code ·········365
13.1.1 安裝 Visual Studio
Code························
366
13.1.2 在 Visual Studio Code 中
安裝 Python
Extension ················
366
13.1.3 建立專案資料夾······ 367
13.1.4 建立程式檔案 ········· 368
13.1.5 除錯程式 ················· 369
13.1.6 其他 Python
編輯器·····················
373
13.2 使用 Tkinter 建立圖形使用者
介面································373
13.2.1 建立圖形應用程式·· 379
13.2.2 網格佈局 ················· 380
13.2.3 建立事件處理器······ 382
13.2.4 建立 mainloop ········· 383
13.2.5 處理 GUI 中的
錯誤·························
383
13.2.6 顯示訊息框 ············· 385
13.2.7 在畫布上繪製 ········· 388
13.2.8 Tkinter 事件············· 391
13.2.9 建立繪製程式 ········· 392
13.2.10 輸入多行文字········ 394
13.2.11 在 Frame 中組合顯示
元素 ·······················
396
13.2.12 使用 GUI 建立可編輯
的 StockItem···········
396
13.2.13 建立一個 Listbox
選擇器····················
402
13.2.14 包含 GUI 的應用
程式 ·······················
408
13.3 本章 小結 ···························410
第 14 章 Python 程式用作網路
客戶端 ·························413
14.1 計算機網路 ····················413

目 錄 XVII
14.2 從 Python 使用 Web ·······422
14.2.1 讀取網頁 ················ 422
14.2.2 使用基於 Web 的
資料 ························
423
14.3 本章小結 ························426
第 15 章 Python 程式用作網路
伺服器························· 429
15.1 在 Python 中建立 Web
伺服器····························429
15.1.1 一臺基於套接字的
小型伺服器·············
429
15.1.2 Python Web 伺服器··· 433
15.1.3 透過檔案支援
網頁 ························
435
15.1.4 從 Web 使用者獲取
資訊 ························
439
15.2 在 Web 上託管 Python
應用程式························443
15.3 本章小結 ························443
第 16 章 使用 pygame 建立
遊戲 ···························· 445
16.1 開始使用 pygame···········445
16.2 使用 pygame 繪圖··········451
16.2.1 影像檔案型別 ········· 451
16.2.2 將影像載入到
遊戲中 ·····················
452
16.2.3 使影像能夠移動······ 454
16.3 從 pygame 獲取使用者
輸入································455
16.4 建立遊戲 Sprite··············457
16.4.1 新增玩家 Sprite ······· 461
16.4.2 控制玩家 Sprite ······· 463
16.4.3 新增 Cracker Sprite·· 464
16.4.4 新增大量 Sprite
例項 ························
465
16.4.5 捕獲薄脆餅乾 ········· 466
16.4.6 新增蕃茄殺手······ 469
16.5 完成遊戲························472
16.5.1 新增啟動螢幕 ········· 472
16.5.2 結束遊戲 ················· 475
16.5.3 遊戲記分 ················· 476
16.6 本章小結························477

第Ⅰ部分
程式設計基礎知識
我們的程式設計啟蒙之旅就此開始!首先介紹計算機實際所做的
工作以及程式語言的含義,然後指導你安裝所需的程式設計工具。接
下來,你將看到使用 Python 語言的第一個步驟,以便告知計算機
為你做事。
第 I 部分講解所有程式使用的 Python 程式語言的基本元素。


開始使用 Python
本章主要內容
首先介紹我們要學習的 Python 程式語言,然後討論使用什麼型別的計算機來
編寫程式,以及如何查詢和安裝用來構建程式碼的工具。還將開始與
Python Shell
互動,並體會程式語言設計者的幽默感。
1.1 什麼是 Python
在開始學習 Python 前,有必要考慮 Python 到底是什麼。 Python 是一門程式設計
語言,換句話說,它是用於編寫程式的語言。程式是一組指令,告訴計算機如何
完成工作。我們無法使用諸如“英語”的語言做到這一點,因為對計算機而言,
嚴格意義上的英語實在是太難理解了。例如,請看以下醫囑:
Drink your medicine after a hot bath. ( 洗熱水澡後服藥 )
你當然可以遵從醫囑,洗上一個熱水澡,再服下藥物。但對計算機而言,則
可能先喝下熱洗澡水,然後喝下藥物。你可用人性化方式解釋上面一句話,因為
英語允許你使用模糊語句。而在設計程式語言時,所寫的指令不能有二義性,必
須是準確的。通常這意味著,需要將動作分解為一系列簡單步驟:
步驟 1 :洗個熱水澡。
步驟
2 :服藥。
程式語言要求我們採用上述方式編寫指令。Python 是多種程式語言中的一種,
1
4 第 I 部分 程式設計基礎知識
為人們提供了一種告知計算機操作的方式。
在我多年的程式設計生涯中,學過多種不同的語言,當然,未來還需要學習更多
語言。沒有一門語言是完美的。我將每門語言視為一種工具,用於具體的情形;
就像我在磚牆、玻璃板或木塊上鑽孔時會選用不同工具一樣。
論及“最優秀的”程式語言時,很多人都顯得十分激動。我也樂於討論
這個話題,就像我討論自己最喜歡的小汽車,但我認為這個問題沒有定論。我
喜歡 Python,是因為 Python 效能卓越,表達清晰;我喜歡 C#程式語言,是因
為我可以藉助它得到結構完好的解決方案;我喜歡 C++程式語言,是由於我可
透過它牢牢控制支援程式執行的硬體……Python 確實有一些令我不滿意之
處,但哪門語言不是這樣呢?所有程式語言各有千秋,我覺得哪一種都是必不
可少的。
1.1.1 Python 的起源
你可能認為,程式語言就像發射太空火箭,由身穿白大褂、學識淵博的科學
家們設計,他們總能在第一時間將一切處理得井井有條,開發的解決方案也完美
無缺。但事實並非如此。由於多種原因,多年來程式語言一直在發展和完善中。
Guido van Rossum 是 Python 最初的開發者。 1989 年末,即聖誕節期間,公
司放假,他決定用幾周時間按自己的愛好開發一個好玩的程式設計專案。他將這門
語言命名為 Python,這不是因為他喜歡大蟒蛇,而是因為他是英國電視喜劇
Monty Python’s Flying Circus (蒙提·派森的飛行馬戲團)的忠實粉絲。憑藉其卓越
的效能和簡明的風格, Python 語言風靡全球。現在, Python 成為最流行的程式設計
語言之一。
1.1.2 Python 版本
Python 有很多版本。在程式設計人員看來,這好像有點兒亂。用一個 Python 版本
編寫的程式未必與用另一個 Python 版本編寫的程式相容。不過,如果所有程式設計人
員都使用相同的 Python 版本,那麼 Python 允許在你的程式中使用由其他人編寫
的程式,這可以節省大量時間和工作。歷經多年的洗練,形形色色的 Python 版本
彙整合兩股不同的發展潮流,這在一定程度上簡化了開發。
選擇 Python 版本時,歸結為選擇 2.7 版本還是 3.
n 版本(其中, n 是不斷遞增
的編號)。
● 2.7 版本(長久以來的骨幹版本)無疑十分優秀,大量現有的軟體都使用 2.7
版本。如果你使用 Python 程式碼庫執行特定任務,庫程式碼很可能是 2.7 版
本的。
● 3.
n 版本(後起之秀)也十分優秀,它去除了很多令人混淆的語言功能。
本書將重點介紹 Python 3. n 版本。你將看到不同版本對程式的影響,另外,
你將考慮如何使用 2.7 版本支援的一些庫。
好在兩種 Python 版本的程式建立基礎是相同的。其實,幾乎所有程式語言都
是互通的; 一旦你學會編寫 Python 程式, 自然可將技術用於 C++、 C#、 Visual Basic
和 JavaScript 等其他很多程式語言。
一旦你掌握了基本駕駛技術,即可將技術運用於幾乎任何交通裝置;同樣,
你可將 Python 程式設計技能運用於其他程式語言。開一輛新車時,只需要在啟程前找
到各種開關按鈕和控制板;在程式設計領域,情況同樣如此。
1.2 打造使用 Python 的場所
如果你是一位大貨車長途司機,在國內出租運輸貨物,當然希望駕駛室內有
舒適的座椅,能看清路況,並能方便地找到和使用控制板。當然,卡車最好有足
夠的動力以較快的速度爬山,在蜿蜒的山路上也能自如前行。
同樣,如果長時間用鍵盤敲擊程式,也需要有一個舒適的工作場所。安裝
好 PC、鍵盤和顯示器;有一把無比舒適的座椅,讓你坐幾個小時都不會感到
睏倦。
寫程式時,計算機不必要效能非凡,但為了支援所用的工具,還是要達到合
理的效能標準,記憶體和 CPU 都要達到一定要求。我建議,裝置的最低配置是 CPU
Intel i5(或同等級別的處理器)、 4GB 記憶體、 256GB 硬碟。使用小型計算機時,開
發難度難免增加,更新程式的時間會延長一些。
所使用的作業系統取決於個人偏好。我喜歡使用 Windows 10,但如果你
喜歡用 Mac OS 或 Linux,也無妨。這三種作業系統都支援 Python 語言及其開
發環境。
1.2.1 獲取工具
在開始共享或銷售程式之前,必須下載和安裝相應的工具。安裝過程需要耗
費一定時間,具體時長取決於網路連線速度。個別情況下,下載和安裝需要你等
待較長的時間。注意,必須按順序執行操作。你只需要對要使用的每臺計算機執
行一次安裝,所以不必心急。
所需要的工具都可供免費下載和安裝。如此卓越的軟體竟然免費供所有人使
用, 確實令人感到驚異和激動!使用 Python 分發版, 可方便地開始編寫程式, Visual
Studio Code 編輯器是建立大型應用程式的理想工具。
對於不同裝置,該工具及其獲得方式都稍有不同。你可從以下網址下載最新
的指令:


1.2.2 Python(適用於 Windows PC)
如果使用 Windows PC,可從 Python 網站下載和安裝 Python。從 Python 下載
站點下載安裝程式,將其安裝在 Windows PC 上。我使用 Microsoft Edge 瀏覽器。
如果你使用其他瀏覽器,看到的螢幕將稍有不同。我建議你使用 Microsoft Edge
瀏覽器執行以下步驟。
務必使用如下官方下載站點,按 Windows 提示執行安裝程式:

圖 1-1 顯示了 Python 的下載頁面。

圖 1-1 Python 下載頁面
網頁中顯示,我正在使用 Windows PC,並提供了兩個下載版本。在下載頁面
上,我想要安裝 Python 3.6.1 版本,因此單擊此按鈕開始下載,如圖 1-2 所示。

圖 1-2 單擊按鈕開始下載
瀏覽器將詢問要對檔案執行什麼操作。如果你使用 Microsoft Edge,則可
看到上面的對話方塊。單擊 Run 按鈕。下載 Python 安裝程式後,將開始執行(見
圖 1-3)。
Python 安裝程式將 Python 下載到你的計算機上,以供使用。可透過多個設定
來更改 Python 的安裝方式,也可不作任何更改。此處的唯一變化是選中安裝程式
對話方塊底部的 Add Python 3.6 to PATH 核取方塊,然後單擊 Install Now。系統可能
要求你確認對系統的更改,單擊 OK 按鈕接受這些更改。

圖 1-3 Python 安裝程式
在安裝的最後,將看到如圖 1-4 所示的視窗,單擊 Close 按鈕關閉視窗。

圖 1-4 安裝成功
安裝臨近結束時,螢幕上可能顯示訊息 Disable path length limit(見圖 1-5),這
指 Windows 管理檔案引用的方式。如果看到這條訊息,單擊 Disable path length
limit,然後確認對計算機設定的更改。
安裝完成後單擊 Close 按鈕,關閉安裝程式。

圖 1-5 單擊 Disable path length limit,確認更改
Python 安裝程式的問題
Python 下載網頁通常可探知你所使用的作業系統,顯示的按鈕將針對你的計
算機自動指向正確檔案。但有時並非如此,你看不到任何直接下載按鈕。如果出
現這種情況,只需要從下載頁面顯示的選項中選擇你使用的作業系統,為你的計
算機找到最新的語言版本。 Python 會定期更新, 因此你所看到的版本可能與圖 1-1
不同(例如,版本可能是 3.6.3)。這不是問題。只要版本號是 3.
n ,就支援本書使用
的示例程式。
1.3 啟動 Python
可啟動支援 Python 語言的環境,並與之互動。就像開啟了新公寓或新房的前
門,或鑽進新購小汽車的車內。
所用的工具稱為 IDLE(Integrated Development Learning Environment,整合的
開發學習環境),又稱 Eric Idle(Monty Python 劇組的一位成員)。在 IDLE 中,可通
過兩種方式與 Python 互動: shell(輸入的 Python 命令將立即執行)或文字編輯器(允
許建立程式程式碼文件)。當今的幾乎所有作業系統都支援 IDLE。

開啟 IDLE
首先開啟 IDLE 環境。在 Windows 10 上單擊
Start 按鈕,然後在 Python 程式組中找到 IDLE(見
圖 1-6)。

有必要在 Start 選單中新增 IDLE,或將其鎖定
到工作列。為此,右擊 IDLE,然後選擇對應的選
項即可。
在 Mac OS 或 Linux 上,開啟終端,輸入 idle,
按下 Enter 鍵。使用哪種作業系統都可以;IDLE 執行後,可使用螢幕上顯示的 IDLE
命令 shell(見圖 1-7)。

圖 1-7 IDLE shell
shell 內有引擎, IDLE 程式包含 Python 引擎。 Python 引擎執行 Python 程式。
IDLE Python Shell 執行你輸入的 Python 命令,將它們輸入到 Python 引擎,然後
顯示結果。

可將 IDLE shell 比作餐廳服務員。你告訴服務員要吃什麼,服務員然後離開
你的座位,轉到廚師那裡告知,此後將廚師做好的食物端到你的桌上。服務員就
像以廚師為中心的 shell。
可使用 IDLE 向 Python 問好(見圖 1-8)。輸入 hello,然後按下 Enter 鍵:

圖 1-8 失敗的問候
嗯,效果欠佳!作為一條經驗法則,如果計算機顯示紅色訊息,通常大事不
妙。這裡,一長串紅色訊息(圖 1-7 中的淺色程式碼部分)指出 Python 不認識單詞 hello。
當你輸入命令時, Python Shell 後的程式將查閱所知的單詞列表, 試圖找到匹配者。
列表中並未定義單詞 hello,於是 Python 顯示這條錯誤訊息。
這就像你向服務員點餐,但廚師不會做。或許 Python Shell 應該顯示 I don't
know what 'hello' means,這樣更加淺顯直白。可以看到,計算機錯誤訊息總將簡
單的錯誤變得十分複雜。
下一章將詳述如何使用 Python Shell,來探討計算機執行程式時到底在做什
麼。此處僅輸入 import this(見圖 1-9),啟用“復活節彩蛋”來結束 shell 會話。

圖 1-9 微妙的 Python
如果你正在尋找“Python哲理”,那麼這就可以算作一條。或許,這也是該
語言“
復活節彩蛋” 歷久彌新的原因。如果你覺得一些話講得過於深奧,不要急,
你將在後續章節瞭解其中的深意。
1.4 本章小結
在第 1 章中,透過安裝 Python 語言和 IDLE 開發環境,打造了一個工作場所。
Python 是一門程式語言,程式語言是英語的簡化版本,允許程式設計人員告知計
算機如何完成任務。
你還與 Python 進行了簡單互動,發現僅有善意沒有多大幫助作用。相反,你
必須給出完全正確的指令,此後才能愉快地交流。
為加深對本章知識點的理解,請思考以下有關計算機、程式和程式設計的“深奧”
問題:
“程式”和“應用程式”有什麼區別?
當談論軟體時,人們往往交替使用“程式”和“應用程式”這兩個詞語。我

用“程式”描述一些程式碼,這些程式碼指示計算機做什麼操作。我用“應用程式”
描述更大和更廣的開發範圍;“應用程式”將程式程式碼以及影像和聲音等資源集
成在一起,給予使用者完整的體驗。 “程式”可能非常簡單,只是幾行 Python 程式碼。
“人工智慧(Artificial Intelligence, AI)”是否意味著終有一天不再需要編寫
程式?
這是一個非常深刻的問題。我個人認為,人工智慧領域的大量從業人員將使
計算機變得足智多謀。給計算機提供大量資訊,並將資訊的關聯方式告知它們。
基於這些素材,程式可根據陳述的上下文準確地推斷和猜測。
人們可“猜測”事物的含義。或許有一天,醫生真想讓我在服藥前喝一些熱
洗澡水(根據本章開頭所列的指令),而我卻錯誤地領會了醫囑。不過總體來看,
人類儲存和綜合分析資訊的能力要強大得多,在表演技能方面,計算機明顯處於
劣勢。或許將來某個時候,這種情況會改變。即使在現在,我們也已看到,在某
些技能領域,如財務、醫療診斷和人工智慧領域,計算機已經作用非凡。不過,
為將我們想做的事情準確告知計算機, 在相當長的時間內, 都離不開程式設計人員……
在你還清房貸前,肯定是這樣。
IDLE 是編寫程式的唯一工具嗎?
IDLE 不是唯一工具。可使用許多工具來建立程式。一些工具完全繫結到一種
特定的程式語言,而一些則更通用。我個人喜歡使用 Visual Studio 工具。 Visual
Studio 可用於包括 Python 在內的多種程式語言。不過,對程式設計新手而言, Visual
Studio 顯得複雜一些,就像開著跑車學習駕駛技術一樣。本書第 III 部分將介紹
Visual Studio 及其姊妹工具 Visual Studio Code。
如果損壞了程式,我該怎麼辦?
一些人擔心,用計算機程式完成的工作可能“受損”。我過去也擔心這一
點。透過始終留一條“後路”,我克服了這種恐懼心理。你或許對此心存恐懼,
現在,你知道如何在計算機上安裝 Python。不大可能僅因為在其中執行程式而
損壞 Python 安裝;即使不幸真的降臨,你損壞了程式,它不能工作了,也不
必過分焦慮,你只需要再安裝一次程式的乾淨副本,然後重新啟動即可。

Python 和程式設計
本章主要內容
你將從本章開始使用 Python 。但在此之前,先來探討程式設計人員和計算機程式實
際做的工作。還將分析
Python 程式語言,討論 Python 在軟體開發領域的地位。
2.1 程式設計人員的工作
如果你此前未編寫過程式,不必擔心。程式設計不是火箭科學。在學習程式設計時,
會對大量的想法和概念感到困惑,這就是難點所在。如果你認為學習編寫程式非
常難,自己沒有能力從事這項工作,我強烈建議你拋棄這些想法。程式設計十分容易,
就像為一群小朋友組織生日聚會一樣簡單。
2.1.1 程式設計和規劃生日聚會
如果要組織一群小朋友參加的生日聚會,就必須確定受邀者。要記住哪位小
朋友愛吃蔬菜比薩,哪幾位小朋友如果坐在一起會打鬧不休。必須考慮每位小朋
友將什麼禮物帶回家,每個人在聚會上的分工。還要規劃好時間,不要讓魔術師
正好趕在飯點到達。為便於規劃,你使用圖 2-1 所示的列表。程式設計與此類似,關
鍵在於“組織”。
如果有能力舉辦一次聚會,就有能力編寫程式。程式設計會有一些特殊之處,但
基本原理是一樣的。由於程式包含可由你建立和管理的元素(與任性的孩子不同),
你可完全掌控所發生的一切。另外,如果編寫過一些程式,你便能開始井井有條
2
地處理所有任務;因此,如果有一點兒程式設計經驗,你會成為更優秀的組織者。

圖 2-1 規劃生日聚會與程式設計類似,讓一切有條不紊地進行
大多數人將程式設計定義為“做的工作誰也弄不懂,但日進斗金。”我將程式設計定義
為“為給定的問題找到解決方案,將方案表示為計算機程式可以理解和執行的形
式。”在該定義中,自然包含如下一兩個事項:
● 只有你能自行解決問題,此後才能編寫程式完成任務。
● 必須讓計算機理解你要它執行什麼操作。
程式有點像食譜。如果你不知道如何烘焙蛋糕,就無法告訴其他人怎麼做。
如果聽者不理解諸如“摺疊麵糰,在其中揉糖”的指令,你仍然無法告訴他如何
烘焙蛋糕。
要建立程式,必須拿出一個解決方案,然後將其分解為多個簡單步驟,使計
算機可以執行。
2.1.2 程式設計和問題
不妨將程式設計人員比作管道工。管道工到達現場時,會背上一包工具和配件。
用一小會兒時間檢視管道問題,然後開啟工具包,取出不同的工具和配件,將各
部分組合在一起,從而解決問題。程式設計與此類似。你有一個要解決的問題,你同
樣有一包可用的工具,即程式語言。你思考了一會兒,想出解決方案。然後將語
言片段組合在一起解決了問題。程式設計藝術在於確定你要從工具包中取出哪些工具
來解決每一部分的問題。
程式設計的有趣之處在於以下藝術:將要解決的問題分成你可交給計算機完成的
一組指令。不過,學習程式並非只是學習程式語言,也不是僅得到一個能解決問
題的程式。編寫程式時,你必須考慮諸多事項,其中一些事項並不與手頭的問題
直接相關。開始時,假設你為客戶編寫程式;客戶有一個問題,希望你能編寫程
序加以解決;還假設客戶對計算機的瞭解不如我們多。
開始時,甚至不會談及程式語言、計算機型別等;此時務必瞭解客戶的需要。

由於程式設計人員為能提供方案而沾沾自喜,當收到客戶的問題時,他們立即思考解
決方案——幾乎是反射性動作。遺憾的是,在很多軟體專案中,由於解決了錯誤
的問題而走向失敗。在實際中,針對一個與客戶無關的問題提供“完美”解決方
案的例子比比皆是。軟體開發人員並未找出哪些是客戶需要的或希望得到的;相
反,開發人員建立了自己想要的東西。客戶認為:開發人員不再問我了,他們正
在構建正確的解決方案。直到最終交付產品時,真相才浮出水面。程式設計人員只有
等到真正準確瞭解客戶的需求後,才能著手構建解決方案。
最糟的情形是,你直接對客戶說“我可以做到。”相反,你首先應該問“客戶
需要這個嗎?”“我真正理解問題嗎?”提出這些問題是一種自律行為。在解決問
題前,你應該有一個有關問題的嚴密定義,這個定義既是你可以接受的,也是客
戶可以接受的。
在現實中,將此類定義稱為“功能設計規範(Functional Design Specification,
FDS)”。 FDS 準確說明客戶的需求。你和客戶都要簽字;如果你能根據設計規範
提供系統,客戶必須支付費用。確定規範後,開始考慮解決問題的方式。
你可能認為,如果編寫一個自用程式,就沒必要寫一套規範。這種想法是錯
誤的。透過編寫某種形式的規範,將迫使你周全地考慮問題,也迫使你考慮你的
系統不需要做什麼。不管是服務客戶,還是編寫自用軟體,都必須編寫清晰的文
檔。規範在一開始就說明了對產品的期望。
專家點津
從頭到尾少不了規範
我編寫過很多商業程式。每次編寫程式時,都首先寫好周密的規範。即使幫
朋友辦事,也照寫不誤,標準絲毫不降低,甚至會更高。
現代開發技術以客戶為中心展開,讓客戶持續參與設計過程。這些方式非常
有幫助作用,因為在專案之初,往往很難寫出明確、周詳的規範。作為一名開發
人員,你對客戶業務的瞭解不會那麼深,而客戶也不瞭解你用於解決問題的技術
的侷限性和可能性。最好構建一系列解決方案版本,與客戶一起討論每個版本的
可行性,再進入下一階段。我們將這稱為“確定原型(prototyping)”。
無論使用哪種程式語言,這都是解決問題的正確方式。無論你做什麼事情,包
括組織一次生日聚會,編寫周密的規範都是十分重要的。
2.1.3 程式設計人員要善於溝通
確定客戶的需要是任何程式設計任務中最重要的一環。不過,在其他很多情形中,
與其他人員的交流也很重要。你可能想要說服一個富有的人支援你的下一個宏偉

目標;也可能想說服一名潛在客戶,你能給出方案,解決他的問題。
並非所有程式設計人員一開始就擅長社交。但有一個要點需要記住:溝通技巧是
可以學習的,就像學習一門新的程式語言一樣。要更好地溝通,你需要走出自覺
舒適的小天地。第一次,誰也不願站在大眾面前講話,但透過練習,你將熟練掌
握溝通技能,讓自己在生意場上走得更遠。
有效溝通同樣可擴充套件到寫作方面。能夠寫文章供他人閱讀,本身就是一項有
用的技能;要提高文筆水平,同樣需要鍛鍊。我建議你從今天就開始寫部落格或寫
日誌。或許,你寫的部落格起初只有你母親才會去看,但務必堅持下去。如果常寫
一些自己感興趣的東西(我喜歡寫程式設計方面的文章,請參見 ),
你的寫作水平將迅速提高。
專家點津
善於溝通的程式設計人員能攬到更有趣的工作,賺取更豐厚的收入
即使你十分木訥,只偶爾從口中迸出幾個單詞,或嘟囔幾句,但只要能快速
寫出滿足特定要求的程式碼,養家餬口就不成問題。但是,那些有趣味的任務
會被善於溝通的人攬走。那些人可以推銷自己的觀點,擅長與客戶溝通,知
道客戶最需要什麼。
2.2 計算機用於處理資料
上面講述了程式設計人員的職責,下面來分析計算機的作用和特殊之處。
2.2.1 機器、計算機和人
人是能製造工具的動物。數千年來,我們發明了很多工具,讓人類的生活變
得更加便利。最初發明瞭機械裝置,如犁,提高了耕地效率。在 20 世紀,我們進
入了電子時代,並在 1946 年發明了計算機。
隨著計算機體型變小,價格降低,計算機滲透到我們生活的各個方面。很多
裝置(如手機)之所以能夠工作,是因為我們將計算機嵌入其中。但要記住計算機
的作用:計算機用於自動完成以前需要人腦完成的操作。計算機談不上絕頂聰明,
它只是按所給的指令做事罷了。
計算機處理資料的方式與香腸機絞肉的方式類似:從一端放入食料,執行一
些處理,從另一端輸出香腸。可將程式比作教練在賽前給球員傳達的指令。教練
可能說:“如果對方從左翼進攻,我希望 Jerry 和 Chris 回防;但如果對方傳球,
我希望 Jerry 能夠截斷。”這樣,開賽後,球員將按計劃行事,從而擊敗對手。

不過,計算機程式與足球隊員有一個重要的區別。如果教練的安排極其荒謬,
球員會發覺。如果教練說:“如果對方從左翼進攻,我希望 Jerry 高唱國歌的第一
段,然後疾速奔向出口”,那麼球員將提出反對意見。
遺憾的是,程式並不知道它所處理的資料是否合理,就像香腸機不知道什麼
是肉一樣。即使將一輛腳踏車放入香腸機,機器也會設法造出香腸。即使將無意
義的資料輸入計算機,計算機也會用這樣的資料去做無意義的事情。在計算機看
來,資料就是傳入的訊號模式,必須遵循一定的方式對其進行處理,來生成另一
類資訊模式。計算機程式是指令序列,告訴計算機如何處理輸入資料,並確定輸
出資料的形式。
下面列出典型的資料處理應用示例(可參見圖 2-2):
● 手機——手機中的微型計算機從無線電波中獲取訊號,將資訊轉換為聲
音。同時,它從麥克風獲取訊號,將其轉換為位模式,透過無線電波傳播
出去。
● 汽車——發動機中的微處理器從感測器那裡獲取資訊, 即發動機當前的速
度、行駛速度、氧氣佔空氣的百分比、加速器設定等。微處理器產生電壓,
控制燃油噴射、火花塞的時長等設定來最佳化發動機效能。
● 遊戲機——計算機從控制器那裡收到指令, 使用這些指令來管理為使用者創
建的虛擬世界。

圖 2-2 裝置中的計算機
當今製造的大多數較複雜裝置都包含資料處理元件,來最佳化效能;當然,個
別裝置包含此類元件或許只起錦上添花的作用。“物聯網”的發展促使計算機滲透
到範圍廣泛的領域。必須認識到,資料處理不僅用於計算員工薪水——計算數字
並列印結果(這是傳統的計算機使用方式)。作為軟體工程師,我們難免要耗費大
量時間將資料處理元件安裝到其他裝置上來驅動它們。這些嵌入式系統意味著,
很多人在不知不覺地使用計算機!

專家點津
軟體是生死攸關的
注意,似乎對人畜無害的程式可能危及人的性命。例如,醫生可能使用你編
寫的電子表格來計算病人的服藥量。此時,如果軟體存在缺陷,將對病人的
身體造成傷害。有關程式設計人員因疏忽導致重大災難的詳細描述,請在網上搜
索 Therac-25。
2.2.2 程式用於處理資料
圖 2-3 顯示了每臺計算機所做的工作。輸入資料到計算機,計算機處理資料,
並輸出資料。我們來決定資料的組成以及輸出的意義,程式也可做到這一點。

圖 2-3 計算機用於處理資料
如上所述,也可將程式視為食譜,如圖 2-4 所示。

圖 2-4 食譜和程式
在本例中,廚師扮演著計算機角色,而食譜是程式,控制廚師使用配料的方
式。食譜中可使用許多不同的配料,程式也可以使用多種不同的輸入。例如,程
序可能獲得你的年齡以及你愛看的電影,並提供輸出,基於合理的等級確定你能
否觀看某部影片。
2.2.3 Python 用於處理資料
可將 Python 本身作為資料處理者(見圖 2-5)。用 Python 編寫的程式可傳給
Python 引擎,然後 Python 引擎生成一些輸出。

圖 2-5 Python 用於處理資料
如上所述,有時輸出是一個錯誤(例如前面輸入 hello 時的情形),有時則是基
於 Python 語言的哲理語句(例如輸入 import this)。讓我們使用 Python 命令 shell 進
一步瞭解 Python 語言的工作原理。
與 Python 對話
上次我們與 Python 交流時,說的話很少。現在,我們要進行更深入的對話,
來進一步瞭解 Python 的工作原理。就像上一章中所做的那樣,首先使用 IDLE 命
令來啟動 Python Shell(見圖 2-6):

圖 2-6 啟動 Python Shell
在第 1 章中, 我們想要問候 Python, 但效果不佳。 因此, 此次我們給命令 shell
提供計算機能理解的指令,可能是數字。輸入數字 2,按下 Enter 鍵(見圖 2-7):

圖 2-7 輸入數字 2,按下 Enter 鍵
這一次,螢幕上未顯示錯誤訊息,只是簡單地回顯了數字 2。看起來, Python
Shell 找到了答案併傳送給我們。為驗證這一點,給它提供一個求和表示式,例如
2+2(見圖 2-8):

圖 2-8 M 提供一個求和表示式
此時, Python Shell 未回顯 2+2,它計算出結果並返回給我們。
看起來, Python Shell 收到我們的指令後執行了一些操作。實際上確實如此。
Python 的核心是一個表示式計算器,會自動計算結果。向 Python Shell 輸入一個
表示式,它就會給出結果。圖 2-9 顯示了一個簡單的表示式。

圖 2-9 對這個簡單表示式進行分析
表示式中的數字稱為“運算數(operand)”, 完成實際工作的是運算子(operator)。
在表示式 2+2 中,有兩個運算數(即兩個 2),有一個運算子(加號)。為 Python Shell
提供一個表示式時, Python Shell 將區分運算子和運算數,並計算出結果。

錯誤的表示式
我們已經看到,如果輸入 Python 不能理解的內容, Python 就提出抗議,顯示
錯誤訊息。如果給 Python 提供無效的表示式,結果同樣如此(見圖 2-10)。

圖 2-10 給 Python 提供無效的表示式
程式設計人員輸入表示式 2+,這是一個無效表示式, Python Shell 明顯不滿,顯
示了一個紅條和一條紅色的錯誤訊息。
Python 擅長處理表示式。如果願意,你完全可用 Python 替代計算器。表示式
的計算方式與數學家計算數字的方式相同,括號的優先順序最高,先計算乘法,再
計算加法。
可用 Python Shell 做一些計算表示式的實驗。從現在起, 不再顯示 Python Shell
的螢幕截圖,只顯示 IDLE 中的輸出結果。也就是說,前面發出的三條 Python 命
令如下所示:
>>> 2
2
>>> 2+2
4
>>> 2+
SyntaxError: invalid syntax
輸入的文字顯示為黑色, Python 的輸出顯示為藍色,命令提示顯示為褐色,
錯誤訊息顯示為紅色。
Python 表示式
本書穿插很多“程式碼分析”特殊段落,這些段落會針對上文的程式碼提示問題。
你可以先自行回答,然後閱讀答案來強化理解。

問:如果嘗試計算 2+3*4,會得到什麼結果?
答: * (星號)是乘法運算子。 Python 用* 替代×(數學中的乘號)。始終在執行
加法運算前執行優先順序更高的乘除運算,因此上述表示式的計算結果是 14。即先
計算 3*4,得到 12,然後加上值 2。如果在 IDLE 中嘗試,將得到相同的結果:
>>> 2+3*4
14
問:如果嘗試計算(2+3)*4,會得到什麼結果?
答:將首先計算括號中的表示式。在上面的表示式中, (2+3)的結果是 5,然
後將 5 與 4 相乘,得到結果 20。
>>> (2+3)*4
20
問:如果嘗試計算(2+3*4,會得到什麼結果?
答: 這是個有趣的問題。 可在 Python Shell 中試一下。 Python 會自我思考:“這
個表示式不完整,需要加一個閉括號”。因此, Python Shell 會等待你繼續輸入。
如果你輸入閉括號,就構成一個完整的表示式;此後將計算值並顯示結果。也可
在第二行新增更多資訊。
>>> (2+3*4
)
14
問:如果嘗試計算)2+3*4,會得到什麼結果?
答:如果 Python Shell 在看到開括號之前看到閉括號,就立即認定程式碼中存
在錯誤,於是顯示一條錯誤訊息:
>>> )2+3*4
SyntaxError: invalid syntax
注意,命令 shell 會突出顯示不正確的字元,嘗試幫助你找到錯誤的出處。
Python 是一門指令碼語言
之所以可以像上面那樣與 Python Shell 對話,是因為 Python 是一門指令碼程式設計
語言。可將 Python Shell 視為 “
機器人演員 ”,執行你提供的任意 Python 命令。
換句話說,你使用 Python 語言告訴命令 shell 你要求程式做什麼。如果“
機器人
演員
”聽不懂你的指令,它就會誠實地反饋(通常顯示紅色文字)。
取出程式,然後執行其中指令的過程稱為“解釋程式”。演員透過表演臺詞來
謀生,計算機透過解釋程式指令為我們解決問題。

專家點津
並非所有程式語言都像 Python 一樣執行
並非所有程式語言都是“指令碼”語言,只有指令碼語言才會採用與 Python 同
樣的解釋方式。有時,程式指令會被轉換為計算機硬體理解的極低階指令。
這個過程稱為編譯(compilation),執行此轉換的程式稱為編譯器(compiler)。
經編譯的指令此後載入到計算機中等待執行。因為執行的是經過編譯的低階
指令,計算機不必分析指令的含義,只是遵照執行,因此該技術生成的程式
的執行速度極快。
你或許因此認定 Python 是執行緩慢的計算機語言,因為每次 Python 程式運
行時,“機器人演員”必須在執行每條命令前確定含義。但這並非真正的問
題,現代計算機的執行速度極快, Python 使用一些聰明的技巧在執行時編
譯程式。
2.3 資料和資訊
現在我們知道,計算機是處理資料的機器,程式告訴計算機如何處理資料。
下面進一步分析資料和資訊的特性。人們交替使用單詞“資料”和“資訊”,但有
必要區分二者,因為計算機和人員以不同方式考慮資料。可分析圖 2-11,其中顯
示了差異。

圖 2-11 資料和資訊
圖 2-11 中的兩項包含相同的資料,只是左側的影像更傾向於描述文件在計算
機中的儲存方式。計算機使用數字值來代表文章中的每個字母和空格。如果你分
析每個值,可找到相應的文字;開頭是值 87,它代表大寫字母 W (位於右側文件
第一段開頭的 When 中)。
考慮到計算機儲存資料的方式,在數字到字母的對映之下還有一層。計算機
中儲存的每個數字都是 on 和 off 訊號的獨特模式(即 1 和 0)。在計算領域,每個 1
或 0 都稱為位。 請參閱 Charles Petzold 撰寫的優秀書籍
Code:The Hidden Language
of Computer Hardware and Software
,以瞭解計算機在此級別的操作方式,以及這
些如何構成所有編碼的基礎。意指大寫字母 W 的數值 87 的儲存方式如下:
1010111
這是數值 87 的二進位制表示形式。由於篇幅所限,此處不精確描述工作原理
(Charles Petzold 已經描述了相關原理)。可將該位模式解釋為: 87=1+2+4+16+64。
該模式中的每一位都告訴計算機硬體是否存在 2 的次方。如果對此不甚瞭解,
也不必過分擔心,但要記住,就計算機而言,資料是由 1 和 0 組成的集合,計算
機儲存和操縱這樣的資料。
而“資訊”是人對資料的解釋。嚴格地講,計算機處理資料,而人處理資訊。
例如,計算機在記憶體某處儲存以下位模式:
11111111 11111111 11111111 00000000
可將其理解為“你從銀行卡透支$256”,或“你所在的位置比水平面低256英
尺”,或“32個照明開關中的8個關了”。通常在人們讀取輸入時,完成從資料到信
息的轉換。再哆嗦一遍,計算機並不知道它處理的資料的含義。在計算機看來,
資料只是位模式;由使用者為這些模式賦予意義。或許你的銀行卡上實際只有$83,
而銀行卻聲稱你擁有$8388608,此時你將能更深刻地理解這一點。
1. Python 中的資料處理
我們知道, Python 用於處理資料。用 Python 編寫的指令碼由 Python 系統來解
釋,此後生成一些輸出。我們也知道,在執行 Python 程式的計算機中,資料值由
位模式表示(on 和 off)。
在 Python 中使用文字
讓我們以 Python 能夠理解的方式向 Python 問好。在 IDLE 中返回 Python Shell,
輸入單詞'hello',這一次,我們將 hello 用單引號括起來:
>>> 'hello'
'hello'
此次沒有顯示錯誤訊息, Python 只是回顯了我們輸入的文字。將這與輸入數
字時的行為進行對比,就會注意到, Python 事實上做的是同樣的事情。上一次,
我們輸入數字 2, Python 回顯 2。此次輸入文字值時, Python 回顯了文字。前面
曾試圖求兩個數字的和;下面試著求兩個文字字串的和:
>>> 'hello' + ' world'
'hello world'
效果不錯,Python 的行為完全合乎預期。我們知道,我們要 Python 求和,Python
就計算結果並返回。前面曾用這種方式求 2 和 2 的和。這裡用同樣的過程求'hello'
和' world'的和。注意,我非常明智地在單詞 world 前加了一個空格;如果不加的
話,程式顯示的結果將是'helloworld'。
Python 內部的處理也十分聰明,不管是數字還是字串,它都能正確地處理
加法(+)。如果讓 Python 求兩個數字的和,它將返回數字。如果讓 Python 將兩個
字串連線起來,它就十分順從地將一個字串連線到另一個字串,返回一個
完整的字串。
違反 Python 規則
問: 如果在輸入字串時漏了閉引號,會發生什麼?
答: 根據前面漏了括號的經驗判斷,你可能認為 Python 會在下一行耐心等著
你給字串輸入閉引號。但實際上,事情不是這樣。
>>> 'hello
SyntaxError: EOL while scanning string literal
“字串字面量”是一個文字字串。字母 EOL 是 End Of Line 的縮寫。Python
Shell 訊息的含義是: 不希望你在字串中輸入換行符。 Python 認為單個運算數(數
字或字串)不能跨越多行。建立一個跨越多行的文字表示式是可以的(你可試一
下),但 Python 不允許表示式的運算數跨越多行。
問: 如果從一個字串中減去一個字串,會發生什麼?
答: Python 非常聰明,能夠分辨出來。因此,你完全可使用減號求兩個數字
的差(你可以嘗試一下);但不能從一個字串減去另一個字串。
>>> 'hello' - ' world'
Traceback (most recent call last):
File "<pyshell#11>", line 1, in <module>
'hello' - ' world'
TypeError: unsupported operand type(s) for -: 'str' and 'str'
Python 詳細解釋了出錯原因,沒有說“減去字串十分愚蠢”,卻給出了較難
理解的描述資訊。為此,需要了解到,“運算數”的含義是“運算子處理的內容”。
這裡,運算子是減號(-),運算數是兩個字串(hello 和 world)。 Python 表明,你
不能在兩個字串之間放置減號。
問: 如果嘗試將數字與字串相加,會發生什麼?
答: 與一個字串減去另一個字串一樣,將數字與字串相加是愚蠢的,
Python自然會顯示錯誤訊息,而且訊息也很難理解。
>>> 'hello' + 2
Traceback (most recent call last):
File "<pyshell#14>", line 1, in <module>
'hello' + 2
TypeError: must be str, not int
但願此次訊息更易於理解。 Python 訊息指出:必須是字串,不能是整數(這
種提示沒有多大幫助作用,它並未告知究竟是哪裡出錯了)。
如果確實想將數字 2 放在單詞'hello'的後面,可將該數字放在引號中:
>>> 'hello' + '2'
'hello2'
>>>
問: 如果嘗試將數字與字串相乘,會發生什麼?
答: 確實可以,會將字串重複給定的次數。
>>> 'hello' * 3
'hellohellohello'
Python 將嘗試在能力範圍內做一些明智的事情。如果交換運算數的順序,這
個表示式依然有效。如果嘗試將字串與零或負數相乘, Python 仍將做一些有意
義的事情。
2. 文字和數值資料型別
如果仔細檢視上述語句的結果, 將會注意到, 當 Python 計算數值表示式時(將
數值作為結果),它僅返回數值;但如果它對字串求值,便返回包括在引號中的
文字,原因在於 Python 遵守有關各種資料的表達方式的規則。
Python 強制分離數值資料(值 2)和文字資料(字串 hello)。對於不同資料型別,
值的儲存方式和操作效果是不同的,即使為每種型別使用相同的運算子也同樣如
此。可使用+運算子將數值或文字字串相加, Python 會識別出操作上下文,確
保得到正確的結果。如果它看到加號位於兩個數字之間,就使用數值版本的+。如
果看到加號位於兩個字串之間,就會使用字串版本的+。
人們也在做同樣的事情。當我們洗臉、洗盤子或清洗房間時,雖然動作都是

“洗”,但每種情況下的實際做法是不同的。如果用英語講,三個動詞都是 wash。
如果只寫一個“洗”字,讀者必須絞盡腦汁,探索會發生什麼事情。當然,計
算機並不擅長“絞盡腦汁”和“探索”。因此,當我們編寫程式時,必須用前後一
致的方式表達我們想做的事情。 Python 和其他程式語言的設計要求我們這樣做。
2.4 使用 Python 函式
我們已經瞭解到 Python 處理文字和數值的方式,現在開始研究實際上如何用
數字(甚至是位模式)表示文字元素。為此,我們使用 Python 自身來探索它如何存
儲值。我們使用 Python 語言內建的一些函式。函式(function)是具有不同名稱的行
為。如果為演員寫劇本,應加上舞臺指導,如“左移”“望著窗外”或我喜歡的“逃
離虎穴”。演員將根據這些在舞臺上完成動作。你將這些視為“函式”,演員一看
到,就知道如何去做。 Python 就像演員,它知道如何執行一組內建的函式。我們
將使用其中一些函式來研究文字在計算機中的表示方式。
專家點津
函式是任何程式語言的重要部分
學習程式語言的一個重要部分是學習它提供的函式。在後面的幾章中,你將
學習一些函式,並開始編寫自己的函式。
每個 Python 函式都有不同的名稱,可能需要為其提供要處理的資料。在這方
面,可將函式視為微型資料處理器,你為函式提供資料,函式生成結果。
2.4.1 ord 函式
Python 知道如何執行的一個操作是 ord, ord 是 ordinal value 的簡寫。初看
ordinal,會感到有些困惑。在這個上下文中,它的意思是“將一系列字元中這個
字元的相應數值傳給我”,或簡言之,“給我提供表示這個字元的數值”。
呼叫函式時,會提供函式的名稱,後跟函式使用的資料(放在小括號中)。
圖 2-12 分析了 ord 函式的呼叫。“給函式提供的資料”的程式名是引數。

圖 2-12 分析函式呼叫
使用 ord 函式研究文字的表示方式
使用 ord 函式研究計算機中儲存文字的方式。首先找到用於表示特定字元的
數值。為 ord 函式提供一個字串,其中只包含一個 W 字元,看看會顯示哪個數
值。在 IDLE 中,給 Python Shell 輸入命令,注意返回的結果。
>>> ord('W')
87
這正是在圖 2-12 中看到的結果。 題目為 Declaration of Independence 一文第一
段的第一個字母 W 對應的值是 87。
但在編寫 Python 表示式時需要十分小心。我們感興趣的 W 必須是文字字元
串的一部分,必須包含在單引號中。如果漏了單引號, Python 系統便認為我們想
瞭解有關 W 事物的資訊,並告知它對 W 事物一無所知。
>>> ord(W)
Traceback (most recent call last):
File "<pyshell#2>", line 1, in <module>
ord(W)
NameError: name 'W' is not defined
Python 程式中不經常使用 ord 函式,但該函式確實提供了一個十分有用的窗
口,使我們能瞭解到 Python 程式碼操縱的值。
2.4.2 chr 函式
ord 函式的一個 Python 補充函式是 chr。 chr 函式接受一個數值引數,並返回
該數值表示的字元。
使用 chr 函式將數值轉換為文字
如果給 chr 函式提供值 87,並沒有什麼實際意義,但我們可以嘗試一下。
>>> chr(87)
'W'
表示字元的數值按合理的方式排列, 這樣, 如果想要顯示與值 88 對應的字元,
你將得到預期的結果:
>>> chr(88)
'X'
在計算機領域,國際標準將特定值對映到特定字元。我編寫計算機程式已經
很多年了,根據我的經驗,我瞭解到字母 A 由值 65 表示,而空格字母(空格很重
要,可用它在文字中間加上空距)由值 32 表示。但通常不需要記住這些數字,因
為 Python 及支援的作業系統將負責顯示文字。我也發現,即使瞭解這些數值,一
起參加聚會的人也對此提不起興趣。
2.4.3 使用 bin 函式探索資料儲存
可將計算機記憶體看作一長串小箱子,每個小箱子都有一個唯一的數值地
址。每個記憶體地址由 8 位組成(on 或 off,如前所述)。此類記憶體地址稱為位元組。
如果你的計算機有 16GB 記憶體,那麼地址數量就是 16G,每個地址的大小是一個
位元組。
單個位元組不能儲存範圍很大的值,因此將多個位元組組合在一起來儲存更大的
數值。後面將講述其工作原理,還將討論 Python 可儲存的值,此處分析用於儲存
值的位模式。
Python 內建的 bin 函式接受一個數值,並返回表示該數值的位串。
確定二進位制表示形式
可使用 bin 函式來探究如何在計算機中儲存資料。
>>> bin(87)
'0b1010111'
bin 函式返回一個字串,該字串是相應數值的二進位制表示形式。注意,這
個字串由 0 和 1 組成。字串開頭的 0b 告訴讀者:這是數值的二進位制表示形式。
構建二進位制數
在 Python 程式中, bin 函式的使用頻率不高(除非有一個特殊客戶,要求你編
寫程式來顯示二進位制值),但我們可使用該函式來研究數值在計算機中的儲存方
式。記住,在計算機硬體中,所有資料都用特定訊號的高低電平來操縱,可認為
0 是零電平, 1 是某一電平。
問: 0 的二進位制值是什麼?
答: 為回答這個問題,也可以使用 bin 函式。
>>> bin(0)
'0b0'
0 值的二進位制值還是 。
問: 1的二進位制值是什麼?
答: 為回答這個問題,也可以使用bin函式,將1作為引數。
>>> bin(1)
'0b1'
1 的二進位制值還是 1。迄今來看,二進位制值並無特別之處。
問: 2 的二進位制值是什麼?
答: 為回答這個問題,也可以使用 bin 函式,將 2 作為引數。
>>> bin(2)
'0b10'
情況發生了變化。要了解原因,首先考慮十進位制數 10,其中的 1 表示該數值
有幾個 10。二進位制數的原理是一樣的,只是此時的 1 告知該數值中有多少個 2;
因此,二進位制值 10 表示 2。
問: 二進位制值 11 表示多少?
答: 我認為,二進位制值 11 是十進位制值 3(2+1),可使用 bin 函式對此進行測試。
>>> bin(3)
'0b11'
從右數第 3 位的 1 是數字 4,第 4 位的 1 是 8,依此類推。你可能想用 bin 函
數來核實數值的位模式,然後檢查結果。
問: 二進位制值 86 與二進位制值 87 的差別是什麼?
答: 可使用 bin 函式對此進行測試。
>>> bin(86)
'0b1010110'
>>> bin(87)
'0b1010111'
比較這兩個二進位制模式可看到,最右側的位從 1 變為 ,因為這一位表
示二進位制值包含 1。最右側包含 1 的數值都是奇數。如果不信,你可以多試
幾個值。
2.5 本章小結
本章學習了計算機的實際工作原理以及程式的作用。從中瞭解到,計算機將
整個世界視為 on 和 off 模式, 該模式表示計算機處理的資料。 計算機處理資料時,
將一種位模式(輸入)轉換為另一種位模式(輸出)。
當人們看到輸出資料並對其執行操作時,資料就變成資訊。計算機並不能像

人類那樣理解所處理的位模式的含義,這意味著,計算機可能以愚蠢的方式處理
資料。
程式告訴計算機如何處理位模式。計算機自身只理解簡單指令,指令必須用
特殊語言(即程式語言)寫成。 Python 是一門程式語言,作為計算機程式執行,它
接收程式指令並按照指令進行操作,就像演員根據劇本表演一樣。
程式設計人員負責將程式建立為一系列指令,這些指令描述要執行的任務。要創
建成功的解決方案,程式設計人員不僅要編寫優秀的程式,還要確保程式真正能完成
使用者要求的任務。這意味著,在程式設計人員編寫任何程式碼之前,務必準確瞭解使用者
需求。與其他人交流,從而瞭解他們需要什麼;要成為一名成功的程式設計人員,這
是一項十分重要的必備技能。
為加深對本章知識點的理解,請思考以下有關計算機、程式和程式設計的“深奧”
問題:
對於像“某人的年齡是–20 歲”這樣的說法,計算機會覺得十分愚蠢嗎?
不會。在計算機看來,年齡值就是一個表示數值的位模式。如果想讓計算機
拋棄負數年齡,你必須將這樣的思想構建到程式中。
如果為汽車的注油系統設定程式輸出,輸出的是資料還是資訊?
一旦開始根據資料採取行動,資料就成為資訊。司機不使用這些值做什麼,
但這些值將改變發動機的速度,這又會影響人員。因此說,這種輸出是資訊而
非資料。
計算機不懂英語,所以說計算機很笨,是這樣嗎?
用英語寫成的句子很難做到完全沒有歧義。律師的主要工作就是精確解釋文
字的含義,並解釋文字在特定情形中的使用方式。人類都不能對某句話的理解達
成一致,因此不能強求計算機正確無誤地理解,不能就此認為計算機很笨。
如果不知道如何解決某個問題,能為其編寫程式嗎?
不能。你能將一些語句堆砌在一起,看看執行時會發生什麼,但不大可能得
到你要的效果。這就像某人喜歡將一堆車輪、齒輪和引擎扔到牆根下,巴望著它
們完美結合在一起,形成一輛能跑的汽車。事實上,編寫程式時,最好經常離開
鍵盤,想一想究竟要用程式完成什麼任務。
主觀認為客戶將“英寸”作為所有物品的尺寸度量單位是明智的想法嗎?
對專案做任何無端的臆測都是不明智的。一名成功的程式設計人員必須確保自己
所做的一切都建立在深入瞭解的基礎之上。你做的任何臆測都會增加發生災難的
可能性。
如果程式做了錯事,是我的責任還是客戶的責任?

32 第 I 部分 程式設計基礎知識
回答這個問題具體取決於:
● 規範正確,程式錯誤:程式設計人員負責
● 規範錯誤,程式正確:客戶負責
● 規範錯誤,程式錯誤:雙方擔責

Python 程式用作網路客戶端
本章主要內容
本章將介紹如何建立與 Internet 和全球資訊網互動的 Python 程式,將介紹計算機
網路的基礎知識,講述如何建立可從
Internet Web 伺服器獲取資訊的程式,分
析用於在程式之間傳遞資料的標準。
14.1 計算機網路
在學習 Python 程式如何使用網路連線前,需要了解一些有關網路的知識。本
章對網路知識不做詳細解釋,只呈現一些背景知識,幫助你瞭解程式的工作方式。
1. 網路通訊
網路使用網線、無線裝置或光纖連線來傳送資料訊號。無論哪種介質,基本
原理都是:硬體將資料以“數字位”格式放在介質上,此後重新獲取資料。位是
0 或 1(也可將位視為 True 或 False),可透過電平高低、發光二級管(LED)的光、無
線訊號來傳遞。設想一下,你可透過開關臥室的燈(如圖 14-1),與住在馬路對

圖 14-1 “房間-房間”網路
14
面房子裡的友人通訊;這就是網路通訊的起點。
一旦你擁有將訊號從一個地方傳送給另一個地方的基本能力,就可以開始傳
輸有用的資料。我們可發明一個協議(訊息和響應的排列方式),並依據協議來傳
遞訊息。要傳遞有用的訊號,必須就訊息格式達成一致意見。你可以說:“如果我
家燈滅,再閃爍兩次,則意味著我姐出去了,你可到我家來;如果閃爍一次,則
你不要過來;如果閃爍三次,你過來時帶上比薩”。這就是協議基礎,通訊各方就
訊息的構建和含義取得一致,來達成協議。
訊息和協議相互獨立。我們可用“敲擊水管”或“噴出煙霧”來替代“燈光
閃爍”,協議都是一樣的。三次閃爍或三次敲擊的意思都是“帶比薩過來”。設計
網路時,可使用層來表示,如圖 14-2 所示。

圖 14-2 網路中的層
物理層傳遞網路事件,協議位於物理層之上。我們可透過燈光閃爍、敲擊水
管或噴出煙霧來傳遞網路訊息。每一層都會建立標準。例如,網路中的“燈光”
物理層的標準將是“一次閃爍時長不超過 0.5 秒,所有閃爍時長不超過 5 秒”。而
“管道”層的標準將描述敲擊的最小響度。
物理層之上的傳輸層不考慮訊息的傳遞方式,它只瞭解已經接收了什麼訊息
事件。可新增新的訊息傳遞方式。例如,可在不更改整個網路的情況下,新增“擺
旗”傳遞方式。 Internet 使用的網路協議基於這種分層方法。
2. 地址訊息
如果有兩位朋友與你住在同一街道,你們想透過臥室燈光通訊系統來傳遞信
息,那麼,該系統將變得更復雜。你必須新增一些地址形式,並指出每個人在網
絡中的唯一地址。現在,訊息由兩部分組成。第一部分是接收方的地址,第二部
分可能包含訊息本身。計算機網路的工作方式與此類似。物理網路的每個部分都
必須具有唯一地址。傳送到某站地址的訊息將由該站中的網路硬體接收。
網路還有廣播地址,允許一個系統向每個系統傳送訊息。在“臥室燈光網路”
中,可使用廣播地址來通知兩位朋友,你的姐姐已經回家,帶回來新交的男友,
因此你家不能再招待其他客人。在計算機網路上,透過廣播,可使新計算機瞭解
網路中重要系統的地址。一個系統可傳送廣播訊息:“各位好,我是新來者”,另
一系統可能響應,響應中包含配置資訊。
網路中的所有工作站都可以接收和處理廣播訊息。事實上,如有必要,工作
站可偵聽在網線或 Wi-Fi 通道上傳送的所有訊息,這當然是個網路問題。就像所

有朋友(以及其他局外人)都可以看到臥室燈光表達的所有訊息一樣,無法阻止有
人偷聽網路上流動的資訊。當連線到安全網路時,計算機將對傳送的所有訊息進
行編碼,這樣,除了預定的接收者之外,偵聽訊息的其他人將一無所獲。
3. 主機和埠
如果想使用臥室燈光閃爍協議與住在同一地址的人員交流資訊,我們需要改
進協議。如果要給 Chris 和 Imogen 傳送訊息,這兩個人住在同一房間。我們需要
改進協議,使包含資料的訊息可以確定接收者。
在計算機系統中,存在同樣的問題。一個給定的計算機伺服器可以給與其連
接的多個客戶機提供大量不同的服務。伺服器可能給一個使用者傳送網頁,給另一
個使用者傳送影片,同時支援 20 個玩家使用的多人遊戲。不同客戶端需要透過一種
方式,找到它們想從伺服器獲得的服務。
Internet 透過使用“埠”達到這個目的。埠是一個編號,用於確定計算機
提供的服務。一些埠“人所共知”;例如埠 80 在傳統上用於網頁。換句話說,
當瀏覽器連線到網頁時,它在使用伺服器的 Internet 地址找到實際計算機,然後
連線到該計算機的埠 80 來獲得網頁。
程式啟動服務時,會將服務所在的埠告知網路軟體。當訊息到達相應埠
時,將訊息傳遞給程式。可以這樣想, Internet 使一個程式可與遠端計算機上的另
一個程式交流。目標程式(可能是 Web 伺服器)可能位於與 Internet 連線的計算機的
一個埠之後。你執行另一個程式(可能是 Web 瀏覽器)建立與該埠的連線,這
樣一來,將可以請求網頁,並將網頁的內容顯示在計算機上。
程式設計人員所寫的程式可使用任意埠號,但很多網路連線包含一個稱為“防
火牆”的元件,防火牆只允許目標地址是廣為人知的特定埠的資料包透過;這
可降低網路系統受到惡意網路程式攻擊的可能性。
4. 使用 Python 傳送網路訊息
上面講述了網路的基本工作原理,現在分析 Python 程式如何使用網路來傳送
和接收訊息。我們將使用 Internet 協議套件中的 UDP(User Datagram Protocol,用
戶資料包協議)來傳送訊息。
傳送網路訊息
要學習網路知識,最好執行操作,將訊息從一個程式傳送到另一個程式。可
在 IDLE中從 Python Command Shell執行此操作。首先啟動 Python Command Shell,
匯入 socket 模組中的所有資源。輸入以下命令並按 Enter 鍵:
>>> import socket
socket 模組包含 socket 類, socket 類用於建立和管理網路連線。首先建立一
個用於接收訊息的 socket 類例項。輸入以下語句並按 Enter 鍵:
>>> listen_socket = socket.socket(socket.AF_INET,socket.SOCK_DGRAM)
socket 建構函式接受兩個引數。第一個是用於指向主機的地址族,這裡將使
用 Internet 地址族,因此使用 socket 模組的 AF_INET 值。第二個引數是要傳送的
訊息的型別。我們將傳送資料包(datagram)。資料包是一個未經確認的訊息,從一
個系統傳送到另一個系統,這與“房屋-房屋”網路透過燈光閃爍將訊息傳送給其
他人(包括正在觀看者和未觀看者)是一樣的。
現在建立套接字,我們需要考慮將連線到的地址。可將網路地址寫成一個元
組。輸入以下語句並按 Enter 鍵:
>>> listen_address = ( 'localhost' , 10001)
資料包是從一個系統傳送給另一個系統的訊息。除非接收者返回確認訊息,
否則資料包的傳送者無法確定訊息是否已被接收。 Internet 協議套件是一組標準,
通常稱為 TCP/IP 套件,用於描述 Internet 和相關網路的工作方式。該標準最初用
於描述傳輸控制協議(Transmission Control Protocol, TCP)和 Internet 協議(Internet
Protocol, IP); TCP 連線網路上的系統, IP 允許在網路之間通訊。可訪問 https:/
/en.wikipedia.org/wiki/User_Datagram_Protocol 來很好地瞭解 UDP 的工作方式。
listen_address 元組包含兩個值。第一個值是要連線到的計算機的地址。最初,
只需要將訊息傳送給自己的計算機上的一個程式,因此使用特殊地址′localhost′來
表示當前計算機。元組的第二個值是程式將要連線到的埠。使用編號(這裡使用
10001)來識別埠。
接下來需要將套接字繫結到將要偵聽的伺服器地址。此後,套接字將可偵聽
地址中給出的埠上的訊息。 bind 方法給出要偵聽的地址,並配置套接字偵聽給
定地址。輸入以下命令並按 Enter 鍵:
>>> listen_socket.bind(listen_address)
現在要求套接字接收一些資料。為此可使用 recvfrom 方法, recvfrom 將獲取
單個資料包。它接受一個引數,引數給出將接受的資料包的最大大小。輸入以下
命令並按 Enter 鍵。
>>> result = listen_socket.recvfrom(4096)
注意,命令視窗未返回>>>提示符,原因是 recvfrom 方法尚未返回結果;它
正在等待資料包的到達。
現在需要製作傳輸器。為此,需要啟動另一個 IDLE Python Command Shell
副本。與偵聽程式一樣,首先需要匯入 socket 模組:

>>> import socket
現在製作傳送套接字。輸入以下語句並按Enter鍵。
>>> send_socket = socket.socket(socket.AF_INET,socket.SOCK_DGRAM)
注意, send_socket 的建立方式與 listen_socket 相同。接下來需要建立地址,
來識別訊息的接收者。我們將給自己傳送訊息,因此使用同一地址。輸入以下語
句並按 Enter 鍵。
>>> listen_address = ( 'localhost' , 10001)
最後,透過網路傳送訊息。輸入以下語句:
>>> send_socket.sendto( b'hello from me' , send_address)
這樣, 將從 IDLE Command Shell 將訊息傳送到埠 1001 中列出的偵聽程式。
按下 Enter 鍵傳送訊息:
>>> send_socket.sendto( b'hello from me' , send_address)
13
>>>
sendto 方法返回已傳送的資料位元組數;此處傳送了 13 個位元組(字串 hello
from me 中的字元數)。你可能會問,為什麼在這個字串的前面加上字母 b?原
因在於, Python 3 通常使用 Unicode 標準對字串字元進行編碼。我們無法透過
套接字傳送 Unicode 值, 但可傳送位元組。 將字母 b 放在字串前面, 可告訴 Python
從位元組(byte)而非 Unicode 字元獲取相應的字串。這樣就傳送了訊息,下面來看
收到的內容。
返回正在執行偵聽器的 IDLE Command Shell。可以看到, >>>提示符已經返
回,因為 recvfrom 方法已經完成,並返回變數 result 中的值。可使用 print 函式查
看結果:
>>> print(result)
當按下 Enter 鍵執行 print 時,將看到 result 的內容是一個元組,元組中包含
兩個條目。第一個條目是一個字串,其中包含傳送者傳送的訊息。第二個條目
是另一個元組,包含傳送訊息的系統的地址。下一個練習將使用這些函式在計算
機之間傳送訊息,其中將討論 Internet 地址。
>>> print(result)
(b'hello from me', ('127.0.0.1', 51883))
這些操作是使用 Internet 的每個程式的基本構件。每當你載入網頁、觀看視
頻或傳送電子郵件時,傳輸資料的方式都是一個程式偵聽資料包,另一個程式發

送資料包。
傳送網路訊息
下面是一些你需要思考的問題。
問: 可傳送除文字外的其他資訊嗎?
答: 可以。資料包傳送位元組值塊,其中可以包含任何型別的資料。上面傳輸
了字串,但你同樣可以方便地傳輸時裝店庫存商品條目。
問: 最大可傳送多大的資料?
答: 可在 recvfrom 方法中設定傳入訊息的最大大小。程式可傳送包含大約
65 000 位元組的訊息。如果傳送更大訊息,則必須分成多個訊息來傳送。幸運的是,
還有其他網路函式可以分離和組合更大的條目。見本章後面的介紹。
問: 如果傳送了訊息,但偵聽器未偵聽到,會發生什麼情況?
答: 什麼都不會發生。我們正在傳送最簡單的訊息型別,即資料包。傳送方
無法瞭解資料包是否已被接收。
問: 偵聽器可偵聽來自另一臺計算機的訊息嗎?
答: 可以。只要訊息從正確的埠(此處是埠 10001)發出,偵聽器將可以偵
聽到。
問: 傳送方可將訊息傳送給其他計算機嗎?
答: 可以。透過使用不同的傳送地址,套接字可將訊息傳送給其他埠和其
他計算機。
問: 偵聽器等候多長時間才能偵聽到訊息?
答: 可能是永久等待。不過, Socket 模組提供了 setdefaulttimeout 方法,該方
法設定 recvfrom 對傳入訊息的等待秒數。如果到時前沒有到達的訊息, recfrom 方
法將丟擲異常。
問: 使用套接字可生成異常嗎?
答: 可以。在網路連線失敗或主機意外斷開連線時,使用網路連線的程式應
當捕獲丟擲的異常。
5. 將訊息傳送到另一臺計算機
sendto 和 recvfrom 方法可用於透過本地網路將訊息傳送給另一臺計算機。可
用這兩個方法來連線家中的兩臺計算機。為此,需要獲取接收訊息的計算機的 IP
地址。可將這個 IP 地址看成計算機在網路上的“電話號碼”。如果計算機沒有 IP
地址,就無法給它傳送訊息。 Python 的 socket 模組包含多個函式,可用於查詢運
行 Python 程式的計算機的 IP 地址。如果載入以下程式,將顯示所在計算機的地
址。此後,將可在傳送程式中使用相應的地址。

# EG14-01 Receive packets on port 10001 from another machine
import socket
host_name = socket.gethostname()
host_ip = socket.gethostbyname(host_name)
print('The IP address of this computer is:', host_ip)
listen_socket = socket.socket(socket.AF_INET,socket.SOCK_DGRAM)
listen_address = (host_ip, 10001)
listen_socket.bind(listen_address)
print('Listening:')
while(True):
reply = listen_socket.recvfrom(4096)
print(reply)
執行上面的接收程式時,它將顯示訊息,給出 IP 地址,然後說明它正在偵聽
輸入:
The IP address of this computer is: 192.168.1.55
Listening:
現在可載入準備傳輸資料的計算機上的傳送程式。
# EG14-02 Send packets on port 10001 to another machine
import socket
import time
# You will need to change this to the address
# of the machine to which you are sending
target_ip = '192.168.1.55'
send_socket = socket.socket(socket.AF_INET,socket.SOCK_DGRAM)
destination_address = (target_ip, 10001)
while(True):
print('Sending:')
send_socket.sendto(b'hello from me', destination_address)
time.sleep(2)
需要將程式中的 target_ip 值改為接收程式顯示的地址。執行傳送程式時,接
收計算機的螢幕上將顯示訊息。可按下 Ctrl+C 鍵或從 IDLE 選單中選擇 Shell |
Interrupt Execution 中止操作。
匯入 socket 模組
將使用
time 模組的 sleep 函式
設定接收訊息的計算機的
IP 地址
建立
socket
設定目標地址
永久迴圈
顯示訊息
傳送訊息
休眠
2 秒鐘
匯入
socket
獲取計算機的主機名
使用主機名獲取
IP 地址
顯示
IP 地址
建立偵聽器套接字
建立偵聽計算機的地址
socket 與地址繫結
永久迴圈
等待傳入的訊息
顯示訊息

6. 路由資料包
我用上述示例程式完成了操作,因為兩臺計算機都連線到我的家庭網路。但
在 Internet 上,並非所有計算機都連線到同一網路。我的家庭網路與鄰居家的網
絡是不同的。 Internet 將大量不同的“本地”網路連線起來。要將訊息從一個網路
傳到另一個網路,必須使用“路由(routing)”方式。
回頭分析“房間-房間”燈光閃爍網路,一位朋友住在大街很遠處,可能無法
看到你家的燈光;但她可看到她鄰居家的燈光。因此,可要求這位鄰居接收訊息,
然後代你將訊息發給你的朋友。這位鄰居可讀取傳入的訊息的地址,如果目的地
是你的朋友,鄰居將再次傳輸訊息。圖 14-3 顯示了工作原理。朋友使用左側視窗
與你交流,使用右側視窗將訊息傳遞給住在遠處的朋友。
你家 朋友鄰居家 遠處的朋友家

圖 14-3 藉助另一個房間實現路由
可認為中間的鄰居家在扮演路由角色。她可連線到兩個網路:鄰居可看到你,
朋友可看到鄰居。鄰居所處的位置使她可從一個網路接收訊息,然後將訊息重新
傳送到另一個網路。與 Internet 的連線由路由器來管理,路由器是一臺計算機,
專門用於使用 Internet 協議傳送和接收訊息。
圖 14-4 顯示了組合方式。家庭網路中的計算機直接連線。桌面 PC 可直接給
印表機傳送訊息。但是,如果桌面 PC 需要從 Microsoft 的 Web server 下載網頁,
則頁面請求必須離開本地網路,透過 Internet 來傳遞。離開本地網路的訊息傳送
給路由器,路由器將訊息轉發給 Internet。路由器還負責接收從 Internet 發往本地
網路的訊息。路由器將這些訊息重新傳輸給本地網路,找到正確的計算機。這個
過程稱為網路地址轉換(Network Address Translation, NAT)。

圖 14-4 路由和 Internet
網路和防火牆問題
我設法使用示例程式 EG14-01 Receive packets on port 10001 from another
machine 和 EG14-02 Send packets on port 10001 to another machine,將訊息從
Windows PC 傳送到 Apple Mac。 Windows 防火牆要求我確認是否允許 Python 程
序使用網路,我確認後,程式開始正常工作。
防火牆是連線到網路的計算機中的網路管理軟體的元件。它嘗試確保程式以
正確方式使用網路連線。如果計算機感染了病毒,防火牆將阻止病毒程式使用網
絡連線來感染其他計算機。防火牆保留了一個列表,其中列出有權使用網路的程
序。如果防火牆檢測到前所未見的程式正在訪問網路,它將要求使用者確認是否允
許新程式使用網路,如圖 14-5 所示。

圖 14-5 要求使用者確認是否允許新程式使用網路
選擇上述對話方塊中的 Allow access 後,網路對話開始正常進行。但是,更難
將訊息從 Mac 傳送到 PC。如果這些程式不工作,原因可能是網路將程式限制到
一組特定埠上。如果兩臺計算機位於不同網路,這些程式也將無法工作。
7. 連線和資料包
Internet 為系統提供了兩種交換資訊的方式:連線和資料包。資料包是從一個
系統發往另一個系統的一條訊息。前面建立的 Python 程式使用資料包。但是,你
也可使用 Internet 來建立網路上系統之間的連線。Internet 使用 TCP 來設定和管理
工作站之間的連線。可訪問
Protocol 來詳細瞭解 TCP。
當兩個系統連線時,它們必須完成一些額外工作來自行管理連線。如果一個
系統在連線期間傳送訊息,網路要麼確認訊息被成功傳輸(即網路收到確認訊息),

要麼顯示一條錯誤訊息,指出無法傳輸。如果必須確保傳遞整個訊息,將使用“連
接”方式。
瀏覽器載入網頁時,計算機和 Web 伺服器共享網路連線,確保傳遞網頁的所
有部分,並重傳失敗的部分。傳輸、確認和再次確認過程意味著資料傳輸速度變
慢。管理連線給參與通訊的系統增加了負擔。對於與另一臺計算機的連線,可認
為其類似於將程式連線到檔案的 file 物件。程式可呼叫連線上的方法,向連線發
送訊息,並檢查是否從連線接收到資料。連線將一直開啟,直到使用連線的一個
系統將其關閉為止。
8. 網路和地址
使用上述測試程式來傳送和接收訊息時,我們使用了諸如 192.168.1.55 的地
址。 前面介紹過, 這稱為 IP 地址, 可將它們視為網路上特定計算機的“電話號碼”。
但誰也不願意去記這樣的 IP 地址。人們更願意使用諸如
的名稱來查詢網站。為解決這個問題, Internet 上的計算機將連線到名稱伺服器,
名稱伺服器將主機名轉換為 IP 地址。後臺系統稱為域名系統(Domain Name
System, DNS)。 DNS 是一組伺服器,負責在自身內部傳遞名稱請求,直至找到具
有一組特定地址的相關係統,將名稱與所需地址匹配。
可將名稱伺服器看成計算機的“查號臺”。過去,如果我想了解本地影院的電
話號碼, 我將致電查號臺。如果計算機想要了解網站的 IP 地址, 將需要查詢 DNS。
14.2 從 Python 使用 Web
Web 是使用 Internet 的服務之一。瀏覽器讀取網頁時,將設定與伺服器的連
接,並請求頁面內容。頁面內容用 HTML(Hypertext Markup Language,超文字標
記語言)來表示。頁面內容可能包括影像和音訊引用, 影像和音訊是網頁的一部分。
瀏覽器將設定連線,下載這些內容,在螢幕上自動渲染網頁。
14.2.1 讀取網頁
如果願意,你可編寫基於套接字的低階程式碼,來設定與 Web 伺服器的 TCP
連線,並取回資料。但由於這十分常用, Python 的建立者已經替我們完成了這項
工作。 urllib 模組使用 Internet 連線與 Web 伺服器通訊,並獲取網頁。 URL 返回與
其關聯的網頁。
# EG14-03 Webpage reader
import urllib.request
url = 'https://'
匯入 URL 讀取模組
這是程式將要讀取的
URL
req = urllib.request.urlopen(url)
for line in req:
print(line)
如果執行上述程式,它將顯示我部落格頁面的當前內容,其中的內容可不少。
urlopen 物件使用 HTTP 請求網頁,然後返回一個可供遍歷的迭代器。
14.2.2 使用基於 Web 的資料
藉助從 Web 讀取內容的能力,不僅能載入網頁文字,也可與其他很多資料服
務互動。其中一個服務是 RSS(Really Simple Syndication 或 Rich Site Summary),
這是一個描述 Web 文章或部落格帖子的格式。很多網站都提供內容的 RSS 源,程式
可連線到 RSS 源,使用其中的內容。
使用上面的網頁讀取程式訪問 https:///journal/rss.xml 來下
載文件,文件中包括我的最新部落格帖子。文件使用 XML 標準格式。
第 5 章使用的天氣 snaps 也從 Web 伺服器獲取天氣資訊。該程式從伺服器下
載天氣資訊(格式是 XML 文件)。
1. XML 文件標準
XML 標準允許我們建立包含結構化資料的文件。文件便於計算機和人員讀取。
程式設計人員建立 XML 文件將資料從一臺計算機傳送到另一臺計算機。 XML 文件包含
大量元素。每個元素都有特性,此類特性與 Python 類的資料特性類似。一個元素
可以包含其他元素。有關 XML 的完整描述,請參閱 。
可使用從我的部落格 RSS 源返回的 XML 文件來分析 XML 的工作方式,如下
所示。我刪除了一些元素,但仍顯示了文件的一般格式(實際上,我對自己的部落格
甚感滿意)。
<rss version="2.0">
<channel>
<title>
robmiles.com
</title>
<item>
<title>
Water Meter Day
</title>
<category>Life</category>
<description>
<![CDATA[ We had a new water meter installed yay!]]>
</description>
</item>
文件中的 rss 元素
rss 元素中的 channel 元素
channel 元素的 title 元素
item 到此結束
部落格帖子的種類
部落格帖子的內容
title 文字
title 元素到此結束
部落格中的
item
item
的標題
建立
Web 請求物件
遍歷
Web 請求,每次一行
顯示行

<item>
<title>
Python now in Visual Studio 2017
</title>
<category>Python</category>
<category>Visual Studio</category>
<description>
<![CDATA[ Python is now available in Visual Studio 2017 yay! ]]>
</description>
</item>
</channel>
</rss>
將 XML 文件組織為元素。元素具有名稱,可包含特性(有關元素的資料,與
Python 類特性類似)。上述示例中的第一個元素是 rss, rss 元素包含一個特性
version, version 特性指出元素包含的 RSS 版本。這與在 Contacts 管理程式中為
Contact 類新增的 version 特性是一樣的。它將 RSS 元素的版本告知程式;在我的
部落格中, version 是 2.0。
<rss version="2.0">
一個元素可包含其他元素,包含在<name>和</name>之間。在上面可看到,
channel 元素包含兩個 item 元素,每個 item 元素又包含 title 和 description 元素。
XML 文件格式
有關 XML 格式,你需要思考以下問題。
問: XML 中的父元素和子元素如何使用?
答: 一個給定的 XML 元素可包含其他元素,這稱為子元素。子元素也可包
含其他子元素。在上面的 RSS 示例中, channel 元素包含兩個 item 子元素。每個
item 都有子元素 title 和 description。
不要將子元素與超類的子類混淆。子類用在類層次結構中,繼承超類(也稱父
類)的所有特性。使用子類,可以定製超類,以更貼合具體情形。這些與 XML 文
檔無關。
最好將 XML 子元素假想為元素的特性(就像是有關元素的資料片段), 但實際
上它是另一個 XML 元素。
問: CDATA 的含義是什麼?
答: 將字串放入 Python 程式,可為它們新增三引號(''')。三引號中的文字可
以跨越多個源程式行,可包含任何引號字元。 XML 文件中的 CDATA 元素的工作
方式與此類似。 <![CDATA[和]]>之間的所有內容都被視為元素的文字。這樣,可
將整個部落格帖子放在 XML 文件的一個元素中。
部落格帖子的種類
部落格帖子的種類
item 到此結束
channel 到此結束
rss 到此結束
item 由此開始
問: 為什麼文件中的第二個 item 包含兩個 category 元素?
答: XML 未對 XML 文件中的內容或組織方式施加強制標準(不過,你可為此
使用 schema,但本書不予討論)。可訪問
schemas/part1.html 來進一步瞭解 XML schema。
可回顧第 11 章建立的時裝店應用程式中使用的標籤, item 的 category 元素與
其類似。讀者可在我的所有部落格中搜尋有關 Python、 Visual Studio 或生活方面的
內容。 RSS 標準允許編寫者根據需要使用足夠多的 category 元素為 item 新增標籤。
2. Python ElementTree
可編寫程式來解碼 XML 檔案,但這是一項艱鉅的工作。幸運的是, Python
提供 ElementTree 類,該類可用於 XML 文件。程式可在 ElementTree 例項中載入
一個 XML 文件,然後呼叫例項上的方法在文件中導航。
# EG14-04 Python ElementTree
import xml.etree.ElementTree as ElementTree
rss_text = '''
<rss version="2.0">
Sample RSS above goes here
</rss>
'''
doc = ElementTree.fromstring(rss_text)
for item in doc.iter('item'):
title = item.find('title').text
print(title.strip())
description = item.find('description').text
print(' ',description.strip())
ElementTree 類提供了一系列方法,可用於查詢和處理 XML 文件中的元素。
為 iter 方法提供元素名,將生成可用 for 迴圈遍歷的迭代。 find 方法將在給定元素
中搜尋具有特定名稱的子元素。元素的 text 特性是元素的實際文字載荷。程式的
輸出如下所示:
Water Meter Day
We had a new water meter installed yay!
Python now in Visual Studio 2017
Python is now available in Visual Studio 2017 yay!
你可使用很多方法來處理 XML 文件, 甚至可使用 ElementTree 類來編輯元素
內容、刪除元素或新增新元素。你可使用上述方法從 Internet 的 XML 源提取資料
RSS 字串建立一個 ElementTree 例項
匯入模組並指定名稱
迭代文件中的所有
item 元素
找到
item 中的 title 元素,從中獲取文字
刪除
title 文字中的多餘空格並顯示
找到
item 中的 description
元素,從中獲取文字
刪除
description 中的多餘空格並顯示
示例程式包含
XML 示例中的所有文字 項。示例程式 EG14-05 RSS Feed reader 包含一些可著手使用的內容。
使用天氣資料
第 5 章中使用的天氣 snaps 解碼 U.S. Weather Service 的 XML 文件。可使用以
下程式碼獲取給定位置的溫度。
# EG14-06 Weather Feed Reader
def get_weather_temp(latitude,longitude):
address = '
query = '?lat={0}&lon={1}&unit=0&lg=english&FcstType=dwml'.\
format(latitude,longitude)
req=urllib.request.urlopen(address+query)
page=req.read()
doc=xml.etree.ElementTree.fromstring(page)
for d in doc.iter('temperature'):
if d.get('type') == 'apparent':
text_temp_value = d.find('value').text
return int(text_temp_value)
可在本章示例程式中的 EG14-06 Weather Feed Reader 資料夾中找到上面的函
數以及伺服器返回的示例天氣檔案。嘗試更改方法,以獲取最高氣溫和最低氣溫,
並預測氣溫。
14.3 本章小結
本章介紹網路程式設計的基本原理,以及網路如何將資料從一臺計算機傳給另一
臺計算機。可以看到,協議描述系統的通訊方式, Internet 使用協議來描述不同功
能層,硬體位於底部,軟體介面位於頂部。計算機之間以資料包形式傳輸資訊,
在本地網路上,每臺計算機都有唯一的 IP 地址。
可認為 Internet 由大量本地網路連線而成。名為“路由器”的裝置將獲取要
傳送到遠端站點(未與本地網路連線的計算機)的資料包,然後將它們傳送到
Internet。網路連線有兩種形式,一種是不予確認的單獨資料包,一種是連線。一
個給定系統可在多個不同埠中的一個上公開連線。程式要接受連線時,會將軟
件套接字繫結到主機上的埠,並接受相應埠上的連線。
透過傳輸大量資料包來傳輸大量資料。 Python 提供一個 socket 類來控制網路
天氣 Web 伺服器
Web 查詢包含經度和緯度
構建
Web 請求
從網站讀取文字
從文字建立
ElementTree
遍歷所有 temperature 元素
相應元素的
type 特性是不是 apparent
獲取
value 元素的內容,
value temperature
的子元素
返回從
value 元素的文字中獲取的整數
連線。可使用 socket,在兩個 Python 程式之間執行簡單通訊,還可使用 urllib 模
塊連線到 Web 伺服器來下載網頁的內容。
最後介紹 XML,討論如何從 XML 文件建立 ElementTree 結構,並從這些文
檔提取資訊。
下面是一個需要思考的有關網路的問題。
無線網路裝置與有線網路裝置使用相同的 Internet 版本嗎?
無線裝置使用的介質與有線裝置不同;但在使用連線的計算機看來,兩種連
接的工作方式是相同的。 Internet 協議允許傳輸方法(在裝置之間移動資料的方式)
作為設定和管理連線的其他層之下的層存在。在第 12 章的時裝店應用程式中,我
們曾使用不同物件來管理資料儲存。只要完好定義了層之間的介面(一個層與另一
層的溝通方式),我們就可以將一層中的一個元件替換為另一個元件,系統的其他
部分不受此影響,將繼續工作。
資料包的上限是多少?
網路的最大傳輸單元(Maximum Transmission Unit, MTU)確定可在一個網路
傳輸事務中傳輸的最大訊息。 MTU 的大小取決於使用的傳輸介質。要了解不同網
絡的 MTU 值,可訪問 。
所有資料包從一個計算機到達另一個計算機時,都經由相同的路線嗎?
未必如此。 Internet 是一個網際網路絡的龐大集合。資料包可能必須在多個網路
之間傳遞,才能到達目的地。負責路由資料包的系統常根據網路各部分的忙碌程
度以及可用連線,確定最佳傳送方式。 Internet 最初用於處理網路的某一部分突然
斷開的情況,因此重路由是 Internet 的固有行為。它可能導致一些怪異的效果;
有時,後傳送的資料包反而更早到達。如果使用套接字設定連線,網路將對程式
隱藏這些效果。
所有資料包都能到達目的地嗎?
並非如此。 UDP 資料包未必能到達目的地。 TCP 資料包是會話的一部分,一
定能到達目的地。
XML 和 HTML 之間有什麼區別?
XML 和 HTML 都是標記語言,故它們的名稱中都包含 ML 字樣。 XML 和
HTML 的內部看起來是相似的,都使用相同格式來描述元素和特性。 XML 是一個
標準,用於描述如何生成任意型別的文件。我可設計一個 XML 文件來呈現足球
得分、乳酪型別以及其他想要操縱的內容,並將這些傳送給另一臺計算機。 HTML
是一門標記語言,專門用於告訴 Web 瀏覽器如何顯示網頁。 HTML 包含相應的元
素,可描述文字格式、影像位置以及背景顏色等。可將 HTML 看成專用於網頁的

XML 文件。
HTML 和 HTTP 之間有什麼不同?
HTML (Hypertext Markup Language,超文字標記語言)告訴瀏覽器在螢幕上顯
示什麼內容。 HTTP (Hyper Text Transfer Protocol,超文字傳輸協議)指出如何將頁
面資料(一個 HTML 文件)從伺服器移到瀏覽器。下一章將進一步介紹 HTTP。

購買地址:

來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/26421423/viewspace-2217242/,如需轉載,請註明出處,否則將追究法律責任。

相關文章