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