PDF源文件地址 : http://www.greenteapress.com/thinkpython/thinkpython.pdfpython
[自述:翻譯第一章花了我大概一週的時間,雖然不是7*8小時的那種翻譯強度,只是工做之餘挑戰一下本身,讓我體會到翻譯就跟本章講的調試同樣,它會讓你抓狂,鬱悶,沮喪。可是最終把這一章翻譯完成了,雖然自我感受翻譯得不是很好,但仍是蠻有收穫感的,有點挑戰自個人意思。目前離翻譯完成還有18章!!!]程序員
本書的目的在於教你如何像一個計算機科學家思考。這種思惟方式結合了像數學,工程學和天然科學的一些有效的特性,就像數學家或者計算機科學家同樣用正式語言去表達想法(尤爲是算法)。讓你可以像工程師那樣設計並安裝組件到系統裏,而且在衆多方案中評估選擇。或者像科學家那樣觀察複雜的系統行爲,創建假設並驗證其真僞。
對於計算機科學家來講最重要一項技能就是解決問題。解決問題意味着提出問題,創造性的思考解決方案,而且清楚準確的表達出解決方案。事實證實,學習編程的過程就是鍛鍊解決問題能力的絕佳機會,所謂熟能生巧。這就是本章的標題爲「編程之道」的緣由。
一方面,學會編程是一項有用的技能。另外一方面,運用編程能夠達成目標。隨着咱們繼續深刻的學習,你會發現這個目標會愈來愈明確。算法
Python是高級語言的一種,或許你還據說過其它的一些高級語言,例如 C, C++, Perl 和 Java 等。固然也有一些低級語言,一般是指所謂的「機器語言」或者「彙編語言」。簡單來講,計算機只能運行低級語言寫的程序。所以高級語言寫的程序運行以前須要處理,這額外的處理是須要時間的,這是高級語言的一個小瑕疵,可是瑕不掩瑜。首先,使用高級語言編程相對容易一些,你只要花不多的時間就能寫出更短,可讀性更強的代碼,也很容易修正;其次,高級語言的可移植性很強,也就是說能夠跨平臺運行(在某些平臺只需作很小的修改,甚至不須要修改),這是低級語言所不具有的特性(如需跨平臺運行必須重寫)。編程
因爲高級語言的這些優點,幾乎全部的程序都是用高級語言編寫,只有不多特定的程序還在使用低級語言。編程語言
有兩種程序能夠把高級語言轉換爲低級語言:解釋器和編譯器。解釋器讀取高級語言而且按程序邏輯執行,而且一次只能執行一個程序,逐行讀取程序並處理運算。解釋器結構如圖1.1所示。函數
圖1.1學習
編譯器則在程序運行以前讀取並轉換。高級程序稱之爲源碼,轉換器稱之爲目標代碼或可執行程序。程序只須要編譯一次,後面能夠重複執行無需其餘處理。編譯器結構如圖1.2所示。測試
圖1.2: 編譯器把源碼轉換成目標代碼, 並由硬件執行器運行.網站
Python程序是由解釋器來執行的,所以它是一種解釋型語言。它支持兩種模式:交互式模式和腳本模式。交互式模式下,你輸入Python代碼,解釋器則輸出結果:spa
>>> 1 + 1
2
「>>>」 是表示Python解釋器就緒的提示符,若是你輸入 1+1,解釋器則會輸出結果2.
或者,你能夠把代碼保存在文件裏,再使用解釋器來執行文件,這就是腳本模式。按照慣例,Python腳本的後綴爲.py。
執行腳本必須提供完整的文件名給解釋器。例如腳本文件名爲 dinsdale.py 在UNIX命令窗口你須要輸入 python dinsdale.py 便可。在其它開發環境運行腳本會有所不一樣,你能夠從Python官網http://python.org查找對應的說明文檔。
交互模式適用於測試較少代碼的狀況,代碼較多的狀況建議採用腳本模式,這樣方便你隨時修改和執行。
程序是爲實現特定目標或解決特定問題而編寫的命令和指令。多是解決數學問題,例如求方程式或求多項式的根,固然也多是符號計算,例如搜索或替換文檔裏的文字或者編譯程序。
不一樣編程語言會有一些差別,可是全部語言都有類似之處:
信不信由你,這些就是編程語言的所有!無論你用過的程序有多麼複雜,它都基本都是由這些指令所組成。所以,你能夠把編程理解爲:把一個很大很複雜的任務拆分紅不少小的子任務,直至簡單到能夠用這些基本的指令來執行爲止。此時概念可能會有點模糊,不過待後面咱們探討到算法的時候,咱們還會回到這個話題上來的。
編程是容易出錯的。程序錯誤稱之爲Bug,而跟蹤除錯的過程稱之爲調試。
3種類型的錯誤能夠在程序裏拋出:語法錯誤,運行時錯誤和語義錯誤。調試過程當中區分這些錯誤類型可讓你很快的消除錯誤。
若是沒有語法錯誤,Python就能夠運行腳本。不然,解釋器就會拋出錯誤信息。語法是指程序結構和語法結構的規則。例如,括號必須是成對出現,如(1+2)是合法的,而缺一個括號,如 8) 則是是語法錯誤。
平常閱讀的時候,讀者每每能夠忍受不少語法錯誤,所以咱們能夠無障礙閱讀E.E.卡明斯的詩歌。而Python則不一樣,只要程序中存在任何語法錯誤,它都會拋出錯誤信息並終止運行。所以在學習編程的初期,你可能會花費較多的時間去跟蹤語法錯誤,但隨着經驗的增加,發現和解決語法錯誤的能力會隨之加強。
第二種類型是運行時錯誤,顧名思義,這種錯誤是發生在程序運行的過程當中的,也能夠稱爲異常。一般表示運行過程當中的突發狀況。本書的前幾章的範例中不多有這種錯誤。
第三種就是語義錯誤。若是程序中有語義錯誤,雖然程序成功運行起來,而且不會產生任何錯誤信息。但事實上程序並無按你所想的那樣去執行指令。
也就是說,程序並不是按你的本意去運行的,你寫的程序在語義上是不對的。判斷語義錯誤相對比較麻煩,此時你只能經過查看程序的輸出結果來搞清楚程序是如何執行指令的。
對程序員而言,調試能力是最重要的能力之一。雖然調試的過程會讓你抓狂,可是你不得不認可調試的過程頗有挑戰性,這偏偏也是編程最大的樂趣。
在某種程度上,調試過程就像偵探破案同樣。各類線索擺在眼前,而後你再推斷出致使結果的事件和過程。
調試也像一門實驗科學,一旦你發現程序有問題,你會不斷的嘗試修改和測試。若是假設是正確的,那測試結果也必定是在預測範圍以內,反之亦然。正如夏洛特.福爾摩斯所說:「當你排除了全部的不可能,剩下的無論有多麼不可能,那必定就是真相。」(柯南道爾,《四人的標誌》)
對有些人來講,編程就是調試。也就是說,編程就是一個逐步調試的過程,直至程序完成你讓它作的事情。在我看來,你能夠從頭開始作一個程序,逐步修改,調試,直至作完一個完整的程序。
例如,Linux是一個開源操做系統,它的核心代碼有上千行,難以想象的是,Linux是由Linus Torvalds編寫的一個探索英特爾80386芯片的一個簡單程序。據拉里.格林菲爾德所說,「Linus 早期作的這個項目,最初只是爲了切換打印內容,並最終演化成如今的Linux系統。」(Linux用戶指南 測試版1)
在後面的章節裏面,我將會對調試和編程實戰提出更多的建議。
天然語言:人們平常交流的語言,如英語,西班牙語,法語等等。這徹底是天然流露,無需刻意修飾的語言。
正式語言:人們爲特定程序設計的語言。例如,數學家在計算中表示數字與符號之間關係的語言就是正式語言;化學家用分子式表示化學結構也是正式語言。所以最重要的是:
正式語言有嚴格的語法要求。例如:3+3=6是正確的算式語句,而3+=3$6則是錯誤的。
語法規則有兩種風格,涉及到符號和結構。符號是語言的基本元素,如單詞,數字,化學元素等。3+=3$6之因此是錯誤的是由於$在數學計算中不是一個合法的符號(至少我是這麼認爲的)。
第二種語法規則也與語句的結構有關,也就是說,符號是按序排列的,3+=3這個語句不對是由於即便+和=是合法的符號,可是卻不能把兩個符號同時放在一塊兒使用(此處存疑,由於C語言中是支持x+=1這種寫法的)。
寫一條語法結構良好可是包含非法符號的句子,而後在寫下一條結構非法可是沒有非法符號的句子。
當你用正式語言閱讀的時候,你必須弄清楚句子的結構(儘管使用天然語言的時候是無心而爲的),這個過程叫作解析。
舉個例子,當你聽到「The penny dropped」,你會想到「The penny」是主語,「dropped」是謂語,當你解析完整個句子,你纔會明白這句話的意思或語義。假設你知道「penny」和「drop」是什麼意思,那麼這句話的意思你就基本清楚了。(字面意思是「錢掉了」,penny有「便士」的意思,習語表示「恍然大悟」的意思)
儘管正式語言和天然語言有不少共同點,例如符號,結構,語義和語法等,可是它們依然有區別:
歧義:
天然語言是具備模糊特性的,人類在使用天然語言的時候是會參考上下文的語境以及其餘相關信息的。而正式語言則不容許有任何歧義,它無論上下文的內容,每一句話只表達一種含義。
冗餘:
爲了減小歧義而且避免誤解,天然語言包含了不少冗餘信息,所以,天然語言有點囉嗦,而正式語言則更加簡潔。
文字:
天然語言裏面包含了不少習語和比喻。正如我前面說的「The penny dropped」,並非說錢掉了(習語是說某人迷惑以後忽然意識到了,有恍然大悟的意思),正式語言則按字面含義來理解。人類使用天然語言確定沒法適應正式語言的這種特性。從某些方面來講,天然語言和正式語言之間的差別就想詩歌和散文同樣,但不只僅如此:
詩歌:
詩歌不只意境深遠並且讀起來押韻惟美,主要是爲了表達做者要抒發的情感,不只晦澀難解,甚至字裏行間刻意爲之!
散文:
散文則側重表達字面含義,字裏行間能提供更多內容,比詩歌更容易分析,可是也有詞不達意的狀況。
程序:
計算機程序是沒有任何歧義的,是能夠經過符號和結構的分析徹底理解的。
這裏有一些閱讀程序的建議(包含其它的正式語言):首先,閱讀正式語言比閱讀天然語言須要更多的時間。另外,結構也很重要,並非說從頭至尾閱讀一字不落的閱讀就能有助於理解。相反,在腦子裏直接解析程序結構和內容更有幫助。最後,細節決定一切,由於在天然語言中小的拼寫錯誤,發音錯誤是能夠忽略的,可是正式語言則否則。
按照慣例,第一個程序一般稱之爲「Hello, World!」,就是在屏幕上輸出文字「Hello, World!」,Python裏面只要這一句就能夠:
print 'Hello, World!'
這是print用法,不是實際意義上的把內容打印在紙張上面,而是把內容打印在顯示器上,此時你能夠在電腦屏幕上看到:
Hello, World!
程序中的引號是不顯示在打印內容裏面的,在Python3版本里,語法略有不一樣:
print('Hello, World!')
「()」在這裏說明print是一個函數,在後面第3章會介紹到函數的內容。在本書都將採用print語句,而不是print函數,若是你用的是Python3版本,請自行轉換,除此以外再無分歧。
若是你在學習本書內容的時候剛好在電腦旁邊,那將是很是好的,你能夠選擇交互模式,即時運行代碼,若是你採用腳本模式那也是很是好的。
嘗試着犯錯有助於你瞭解語言的新特性,例如:把「Hello, World!」程序裏的引號去掉一個,或者兩個引號都去掉,又或者把print拼寫錯了將會致使什麼結果?這種類型的實驗不只能夠幫助你記住所學的內容,並且能夠幫助你調試,由於在這個過程當中你將瞭解錯誤消息的含義。在這個階段故意犯錯誤比無心中犯錯要好。
編程的過程當中,尤爲是在調試的時候每每會讓你情緒激動,甚至與大BUG糾纏的時候你會感到憤怒,沮喪而且難堪。
事實證實,人對電腦的反應跟人對人的反應是同樣的。當電腦運行良好的時候,咱們會把他們當成隊友,當電腦表現粗魯或者執拗的時候,咱們對他們的態度也是同樣。
預先了解電腦的這些特性或許對你有幫助,一是把電腦當成一個具備精確計算能力的員工,另外電腦有特定的缺陷,好比缺少同理心沒有大局觀。你的工做就是作一個優秀的管理者,發揮電腦的優點,弱化電腦的缺陷,不要由於情緒而影響到工做效率。雖然說調試工做會讓人沮喪,但它的確是頗有價值的一項技能,即便是對編程之外的事情也是頗有價值的。在本書的每一章結尾都會有調式的部分,指望這部份內容可以幫助到你。
問題解決
表述問題,找到解決方案並表述解決方案的過程
高級語言
像Python這樣爲了便於人類讀寫而設計的語言
低級語言
爲計算機執行而設計的語言:機器語言,彙編語言
可移植性
程序能夠在不一樣平臺運行的屬性
解釋
逐行翻譯並執行高級語言編寫的代碼
編譯
一次性把高級語言寫的程序翻譯成二進制指令序列,造成目標代碼
源代碼
用高級語言編寫的,未經編譯的字符流
目標代碼
源代碼通過編譯器編譯以後輸出對象
可執行程序
目標代碼的另外一個表述:可執行文件
提示符
解釋器顯示的字符,表示能夠接收用戶的輸入
腳本
存儲在文件中的程序代碼(一般須要解釋器進行翻譯)
交互模式
在Python解釋器中輸入代碼並執行
腳本模式
用Python解釋器讀取文件中的代碼並執行
程序
制定計算的指令集
算法
解決同類型問題的通常過程
Bug
程序中的錯誤
調試
發現並解釋發現的3中錯誤類型
語法
程序結構
語法錯誤
程序中沒法完成語法解析的錯誤
異常
程序運行中檢測到的錯誤
語義
程序的含義
語義錯誤
程序中的一種錯誤,它讓程序不按程序員的意圖執行指令
天然語言
人類交流所使用的語言
正式語言
人類設計用於特殊目的,如表示數學思想或計算程序。全部程序語言都是正式語言。
符號
程序語法結構的基本要素之一,相似於天然語言裏的單詞。
解析
檢查程序並分析其語法結構。
打印語句
用Python解釋器在屏幕上顯示值
練習2
訪問Python網站http://python.org 。這個頁面包含了Python的信息以及和Python相關信息的頁面,你能搜索到Python的文檔。
例如,你在搜索框輸入print,你看到第一個連接就是print語句的文檔。搜索結果並不是全都對你有幫助,可是聊勝於無。
練習3
打開Python解釋器,輸入help()便可打開在線幫助程序,或者直接輸入help('print')能夠獲取到跟print
語句相關的信息。若是不行的話,你須要檢查一下是否安裝了Python或者檢查一下環境變量,具體跟你的操做系統和Python版本有關。
練習4
打開Python解釋器把它當成一個計算器。Python的數學計算語法幾乎跟標準數學運算是同樣的。例如+,-和/分別表示加,減和除,固然,正如你所料想的那樣,乘法符號是 * 。若是參加一個10千米長跑花了43分鐘30秒,那麼你的時速是多少英里?(提示:1英里大約1.61千米)
print(10/((43*60+30)/60/60)/1.61)
計算結果:
8.567144998929107