生產(chǎn)力水平的發(fā)展是人類歷史的主旋律。決定生產(chǎn)力水平的重要因素之一是生產(chǎn)工具。從這個角度講,人類歷史就是從石塊到計算機的歷史:從石器時代到信息時代。計算機是信息時代的主要生產(chǎn)工具,為了掌握這種工具,就要學習程序設計語言。
程序設計語言很多,相關的書籍更多。初學者常困惑于如何選擇入門語言①,一旦決定后又困惑于選擇什么教材。令人沮喪的是,選擇的機會成本并不低:一般初學者完整地學習某門編程語言需要一個月甚至更多時間。大專院校課程改革的機會成本則更高。有人說選擇什么語言入門不重要,成為高手后自然兼通各種語言。這種說法忽視了大多數(shù)學習者并不會成為高手的事實,而且選擇性遺忘了他們自己作為初學者時所走的彎路。總而言之,學習者和教師在選擇適合入門的編程語言和書籍時應當謹慎行事。因此筆者有必要在前言中將寫作意圖和內(nèi)容取舍進行說明,以作為讀者選擇的依據(jù)。
寫作背景和目的
筆者在2018年秋接到邀約并著手寫作,全稿終于2019年春。此時Python已經(jīng)躋身主流語言之列。之所以稱其為主流語言,在筆者看來有以下幾點證據(jù):
? 在各類有影響力的語言排行榜上,使用Python的比例開始占據(jù)較大份額,排名也很靠前②;
? 在許多領域,Python成為主要的編程語言,甚至是首選語言,例如在數(shù)據(jù)分析、人工智能和服務器開發(fā)等領域;
? 教育部將Python納入了國家計算機等級考試的科目③。
而在此之前其已經(jīng)得到了廣泛應用:
? Python逐漸成為許多國際一流高校程序設計課程的教學語言;
? 許多基礎軟件框架采用Python作為設計語言或提供Python的編程接口;
? Python在開源軟件界和工業(yè)界已廣受歡迎。
上述事實是筆者決定基于Python編寫本書的原因④。其他的原因則是在教學中無合適教材可用。數(shù)年前筆者領導團隊設計Python課程體系,那時曾經(jīng)遍訪各種Python書籍和教程。當時的Python書籍或者是簡單的手把手入門,或者是大部頭的知識大全,或者是應用于某具體領域的手冊指南。
隨著近年來Python教學實踐的展開,市面上開始出現(xiàn)各種教科書體裁的Python書籍(如羅伯特塞奇威克等所著的《程序設計導論:Python語言實踐》)。那為何還要再寫一本同樣主題的教科書呢?因為教學對象不同,教學目標有所差別,教學過程各有側(cè)重。所以教科書的首要價值在于不同。這種不同在本書來說至少有兩個層面,一是Python與其他語言的不同,二是本書與其他Python書籍的不同。
學習或講授新知識時,首先應注意到的往往是其與原有認知的相同之處,但唯有深入理解并能運用其不同后,才算窺得門徑。例如Python也有循環(huán)、分支和函數(shù)等各種語言俱有之概念,但學習者如只見共性,并由此得出Python很簡單的結論,便失去了學習新語言的意義。教師在教學生時也不能僅僅按照講授舊有語言的經(jīng)驗,把講義中的例子依次用Python重寫一遍了事。①
書的不同則在于體裁形式、內(nèi)容取舍編排和作者觀點的不同。既然是教科書,總不大好寫成對話體,也不適宜畫成漫畫②。所以教科書的不同主要體現(xiàn)在取舍、次序、示例和觀點等方面。然而寫一本完全不一樣的書是很難的,尤其是在Python已經(jīng)相當流行的當下。③
不同總是相對的,各種相對性參照中,對讀者來說最重要的參照便是讀者自身。初來者看處處皆是新奇,見多識廣后則覺得不過爾爾。所以下文僅對本書內(nèi)容的取舍和編排進行說明,至于其中有何不同則留待讀者自己體會。
取舍
在教科書中全面講授Python的細節(jié)是不現(xiàn)實的(這里說的語法細節(jié)包括完整的語法模型、各種對象的API④,以及各種標準庫),原因有以下幾點:
? 過多的細節(jié)會喧賓奪主,無法凸顯真正重要的核心內(nèi)容;
? 語言中的艱深部分不適合本書面向的教學階段,也不常用于多數(shù)程序員的日常工作;
? Python標準庫包羅萬象,全面介紹是不現(xiàn)實的(無論從篇幅上還是讀者的知識背景基礎而言);
? Python在不斷發(fā)展,其細節(jié)仍然在不斷變化中。
筆者認為,既然在整體上無法面面俱到,那么在局部也不應有這種負擔。例如異常處理這一主題,如果完整地講授異常機制的每個細節(jié)(如各種內(nèi)建異常類型),則需要相當多的篇幅①。但真實的情況是:絕大多數(shù)的工程師根本不懂如何處理程序的意外情況,不論是使用C語言這樣沒有異常處理機制的語言,還是使用Java或Python這樣有完整異常處理機制的語言。究其原因有以下幾點:
? 一是初學者沒有能力接受太多的異常處理知識,正常程序還寫不明白,哪里有精力去整什么異常處理;
? 二是異常處理的核心在于全面、準確地剖析程序的各種意外情況,不具備這個能力,學習再多的異常處理機制也是枉然;
? 三是在學習程序設計的初級階段,往往用算法進行練習(比如走個迷宮、匹配個字符串),不和復雜的外部世界(如網(wǎng)絡)打交道;
? 四是考慮到教學重點和敘述篇幅,也往往假定數(shù)據(jù)有效,這樣就不用考慮處理意外情況。這樣一來,教學中費大力氣講授的異常處理機制,也因為暫時無用而被拋諸腦后。
本書則不糾纏于異常處理的細節(jié)和內(nèi)建異常的類型,而是在講述完基本語法后詳細剖析一個程序?qū)嵗?.10.2節(jié)),展示如何分析和處理各種意外的輸入情況,篇幅上也僅限制為一節(jié)。讀者若能吃透這一部分內(nèi)容,則當有編寫健壯程序的意識,自能夠在工作中舉一反三,也無須筆者再行贅述。反之,若對健壯性不夠重視,則多費篇幅也沒有意義。
作為這種取舍思路的補充,本書有時會指出一些自學內(nèi)容,將其留作練習,并引導讀者進行思考或通過網(wǎng)絡查閱相關資料。作為編程入門教科書,本書首要講述程序設計的一般性方法,例如:
? 數(shù)據(jù)類型、流程控制、輸入/輸出和函數(shù)等基本手段;
? 狀態(tài)機、遞歸、函數(shù)式編程等高級技巧;
? 數(shù)據(jù)結構和算法;
? 面向?qū)ο蟮脑O計思想。
對Python自身語法的介紹,也在本書各部分占據(jù)了相當篇幅。然而本書終歸不是語法手冊,所以并不追求語法知識細節(jié)的完整性。書中大部分小節(jié)后會給出延伸的問題和練習,或是明確的編碼練習,或是要求讀者進行深入地學習和思考,統(tǒng)稱為思考和擴展練習。本書在設計和挑選例題時力圖做到和傳統(tǒng)的程序設計入門書籍在角度和深度上有所差異,目的在于為學生和教師提供更加開闊的思路。
計算機程序設計的理論基石(如語言基本模型、數(shù)據(jù)結構和算法)是在半個世紀前奠定的。雖然Python誕生的年代稍晚,但也基于這些基石構建而成。Python的主體部分是基于樸素平實的想法構建而成,而非天才的靈光一現(xiàn)。本書的一個重要初衷就是將這些樸素呈現(xiàn)給讀者。筆者舍去了一些和該初衷無關的內(nèi)容,如傳統(tǒng)教學中往往著重介紹的字符串顯示控制標記,在本書中只是一帶而過。而那些更為深層次的基本概念則得到了強化,例如狀態(tài)機模型、遞歸消除、面向?qū)ο髣訖C及性能權衡等。
本書在示例中堅持給出完整可執(zhí)行的代碼或交互界面步驟,然而本書絕非手把手的教程。書中有些內(nèi)容對于學習者來說是具有相當難度的,需要讀者反復閱讀思考并且動手實踐才能夠理解或掌握。這種難度是具有現(xiàn)實意義的:較難內(nèi)容大多數(shù)來自于工程實踐、后續(xù)學習,甚至是求職面試中的重點。讀者應當認識到對這些問題的思考能力和思考過程的重要性。
內(nèi)容編排
本書分為4章,取名為:
? 第1章 基礎;
? 第2章 函數(shù);
? 第3章 數(shù)據(jù)結構;
? 第4章 面向?qū)ο蟆?/p>
上述各章內(nèi)容并非涇渭分明,原因主要在于Python的知識點存在許多循環(huán)依賴,如圖1所示。例如for循環(huán)用到了迭代器的概念,而講授迭代器需要足夠的面向?qū)ο笾R,繞過分支控制先完整地講述面向?qū)ο笠膊滑F(xiàn)實。對于有經(jīng)驗的讀者來說,這沒有任何問題,但對初學者則會造成很大困擾。基于這些原因及教學實踐,本書在第1章中簡要講授了函數(shù)定義而非拖至第2章,將定義類的基本方法提前至第2章而不是留待第4章。這兩節(jié)內(nèi)容的調(diào)整是本書的重要關節(jié)。
圖1 知識點的循環(huán)依賴
這4章內(nèi)容以第1章篇幅最長,第2、3章次之,第4章最短。程序的基本設計方法、異常處理和程序調(diào)試等內(nèi)容歸入了第1章。模塊和迭代器歸入了第2章。部分內(nèi)建類型,如字典的深入講解歸入了第3章。在第4章面向?qū)ο笤O計部分,考慮到相應的學習階段課時、Python的混合風格特性和簡潔的面向?qū)ο笳Z法,筆者決定精簡篇幅而非長篇大論。另外,由于在Python中對象模型和面向?qū)ο笳{(diào)用風格的無處不在,許多相關知識已經(jīng)散見于前3章,也沒必要再次重復講述。
習題
本書沒有單獨整理的習題集。首先是因為筆者水平所限,并且時間也有限,無法設計大量的原創(chuàng)習題。另一個原因是筆者反對采用在語言學習階段使用刷題的方式提升編程能力①。讀者如能將本書示例及每小節(jié)末尾的思考和擴展練習完成,在筆者看來就足夠了。如果讀者在完成這些內(nèi)容后仍覺不足,不要把精力浪費在所謂的習題集或面試寶典上,而應該去學習更為深入的主題(如操作系統(tǒng)、網(wǎng)絡、算法或編譯原理等),或投身于解決實際問題。
參考文獻
本書中提到的若干算法、觀點、文檔和源碼的原始出處在書尾以參考文獻的形式給出。閱讀原始文獻是非常有必要的。通過對這些文獻的閱讀,即便是少量閱讀,學習者也能夠體會到創(chuàng)造者當時的心境。這看似增加了額外的學習任務,但實為捷徑。為了便于讀者檢索,筆者用[1][2]的編排格式給出了所對應的參考文獻序號。
版本
筆者在Mac計算機上完成了絕大部分的寫作工作。寫作時的Python最新版本是3.7。當然這絕不意味著讀者也需要搞一套這樣的軟硬件環(huán)境。使用Linux的讀者不用太過擔心兼容性問題。使用Windows系統(tǒng)的讀者除去1.6.3節(jié)中管道行的相關命令外,應當可以順利運行本書中的其他程序。筆者平時并不使用Windows系統(tǒng),所以本書示例在Windows平臺上可能會稍有更多的兼容性問題。但跨平臺的兼容性帶來的麻煩遠不及Python本身升級帶來的兼容性問題。所以在學習時糾結于應當使用哪種操作系統(tǒng)平臺是意義不大的,因為Python未來的某次升級可能導致本書代碼無法運行的情況更多。好在互聯(lián)網(wǎng)的便利使得筆者對本書出版后做勘誤和代碼更新很容易,筆者會將本書的勘誤信息和最新的升級信息反饋給出版社,讀者可在出版社的官網(wǎng)上找到本書,獲取這些資料。
格式約定
為了便于讀者學習,本書堅持給出絕大多數(shù)示例的完整代碼及運行效果。有的代碼示例直接運行即可看到期望的結果,而有的代碼則需要進行一些樣例輸入或者將其導入后調(diào)用。本書統(tǒng)一將這些運行結果或運行示例稱為程序運行結果。
本書用以下格式表示代碼實例。這些實例大部分能夠直接運行,少部分需要讀者自行補充完整。
本書用以下格式表示交互執(zhí)行的過程和結果。
其中, $ 表示操作系統(tǒng)的終端(shell)提示符,>>>表示Python的交互式執(zhí)行環(huán)境提示符。該格式還用來排版批量的文本,例如:
至于在說明文字中用到的解釋性代碼,則直接用如下格式排版:
本書的代碼參考Python的推薦風格PEP-8,但有時為了行文緊湊也會縮減空格及空行。
獲取配書資料
本書提供以下配書資料:
? 配套教學視頻;
? 實例源代碼文件;
? 教學PPT。
這些資料需要讀者自行下載。請登錄華章公司網(wǎng)站,在該網(wǎng)站上搜索到本書,然后單擊資料下載按鈕,即可在本書頁面上找到下載鏈接。
讀者對象
本書的最佳讀者設定是有教師指導的程序設計初學者,筆者稱之為教科書設定。這意味著本書不會教讀者諸如安裝執(zhí)行環(huán)境和使用代碼編輯器這類準備工作。這是教師的職責。如果讀者是自學者,那么你應當首先確保自己正確地安裝了Python運行環(huán)境,并嘗試編輯一兩個Python小程序運行一下。這在今天很容易,讀者只需要隨便找一個在線視頻,看上二三十分鐘即可。對于自學者來說,找到幾位Python的使用者去獲取一些初始建議,并且能夠在學習遇到困惑時求助也是非常重要的。很多人在學習過程中因為某些不經(jīng)意的障礙而放棄。比如原本代碼寫對了,但某個執(zhí)行路徑不對,在反復檢查代碼后依然失敗而信心全無。
本書還特別適合一類讀者,即學過一些程序設計語言的粗淺知識,馬馬虎虎地寫過一些程序,處于某種目的又希望認真、正式地學習程序設計的學生。他們有可能是打算大學畢業(yè)希望找一份IT工程師工作的學生,也可能是中學階段學過一些編程后希望在這條路上走得更遠的學生。對這類讀者來說,本書將帶給他們更加深厚的基礎能力。
致謝
本書的寫作得到了好友姜寒先生的大力協(xié)助。姜先生有豐富的實踐經(jīng)驗,又兼通各種主流程序設計語言。筆者在寫作本書時多有疑難困阻,或關于Python本身,或關于其他廣泛主題;又有時在詳略取舍上難以決斷,或是對一些觀點信心不足。每每及此,與姜先生討論后總能破除心中所障。除此之外,姜先生還審閱了本書的部分章節(jié),從內(nèi)容到行文,均提出了寶貴意見。
張頔于北京