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