生产力水平的发展是人类历史的主旋律。决定生产力水平的重要因素之一是生产工具。从这个角度讲,人类历史就是从石块到计算机的历史:从石器时代到信息时代。计算机是信息时代的主要生产工具,为了掌握这种工具,就要学习程序设计语言。
程序设计语言很多,相关的书籍更多。初学者常困惑于如何选择入门语言①,一旦决定后又困惑于选择什么教材。令人沮丧的是,选择的机会成本并不低:一般初学者完整地学习某门编程语言需要一个月甚至更多时间。大专院校课程改革的机会成本则更高。有人说选择什么语言入门不重要,成为高手后自然兼通各种语言。这种说法忽视了大多数学习者并不会成为高手的事实,而且选择性遗忘了他们自己作为初学者时所走的弯路。总而言之,学习者和教师在选择适合入门的编程语言和书籍时应当谨慎行事。因此笔者有必要在前言中将写作意图和内容取舍进行说明,以作为读者选择的依据。
写作背景和目的
笔者在2018年秋接到邀约并着手写作,全稿终于2019年春。此时Python已经跻身主流语言之列。之所以称其为主流语言,在笔者看来有以下几点证据:
? 在各类有影响力的语言排行榜上,使用Python的比例开始占据较大份额,排名也很靠前②;
? 在许多领域,Python成为主要的编程语言,甚至是首选语言,例如在数据分析、人工智能和服务器开发等领域;
? 教育部将Python纳入了国家计算机等级考试的科目③。
而在此之前其已经得到了广泛应用:
? Python逐渐成为许多国际一流高校程序设计课程的教学语言;
? 许多基础软件框架采用Python作为设计语言或提供Python的编程接口;
? Python在开源软件界和工业界已广受欢迎。
上述事实是笔者决定基于Python编写本书的原因④。其他的原因则是在教学中无合适教材可用。数年前笔者领导团队设计Python课程体系,那时曾经遍访各种Python书籍和教程。当时的Python书籍或者是简单的手把手入门,或者是大部头的知识大全,或者是应用于某具体领域的手册指南。
随着近年来Python教学实践的展开,市面上开始出现各种教科书体裁的Python书籍(如罗伯特塞奇威克等所著的《程序设计导论:Python语言实践》)。那为何还要再写一本同样主题的教科书呢?因为教学对象不同,教学目标有所差别,教学过程各有侧重。所以教科书的首要价值在于不同。这种不同在本书来说至少有两个层面,一是Python与其他语言的不同,二是本书与其他Python书籍的不同。
学习或讲授新知识时,首先应注意到的往往是其与原有认知的相同之处,但唯有深入理解并能运用其不同后,才算窥得门径。例如Python也有循环、分支和函数等各种语言俱有之概念,但学习者如只见共性,并由此得出Python很简单的结论,便失去了学习新语言的意义。教师在教学生时也不能仅仅按照讲授旧有语言的经验,把讲义中的例子依次用Python重写一遍了事。①
书的不同则在于体裁形式、内容取舍编排和作者观点的不同。既然是教科书,总不大好写成对话体,也不适宜画成漫画②。所以教科书的不同主要体现在取舍、次序、示例和观点等方面。然而写一本完全不一样的书是很难的,尤其是在Python已经相当流行的当下。③
不同总是相对的,各种相对性参照中,对读者来说最重要的参照便是读者自身。初来者看处处皆是新奇,见多识广后则觉得不过尔尔。所以下文仅对本书内容的取舍和编排进行说明,至于其中有何不同则留待读者自己体会。
取舍
在教科书中全面讲授Python的细节是不现实的(这里说的语法细节包括完整的语法模型、各种对象的API④,以及各种标准库),原因有以下几点:
? 过多的细节会喧宾夺主,无法凸显真正重要的核心内容;
? 语言中的艰深部分不适合本书面向的教学阶段,也不常用于多数程序员的日常工作;
? Python标准库包罗万象,全面介绍是不现实的(无论从篇幅上还是读者的知识背景基础而言);
? Python在不断发展,其细节仍然在不断变化中。
笔者认为,既然在整体上无法面面俱到,那么在局部也不应有这种负担。例如异常处理这一主题,如果完整地讲授异常机制的每个细节(如各种内建异常类型),则需要相当多的篇幅①。但真实的情况是:绝大多数的工程师根本不懂如何处理程序的意外情况,不论是使用C语言这样没有异常处理机制的语言,还是使用Java或Python这样有完整异常处理机制的语言。究其原因有以下几点:
? 一是初学者没有能力接受太多的异常处理知识,正常程序还写不明白,哪里有精力去整什么异常处理;
? 二是异常处理的核心在于全面、准确地剖析程序的各种意外情况,不具备这个能力,学习再多的异常处理机制也是枉然;
? 三是在学习程序设计的初级阶段,往往用算法进行练习(比如走个迷宫、匹配个字符串),不和复杂的外部世界(如网络)打交道;
? 四是考虑到教学重点和叙述篇幅,也往往假定数据有效,这样就不用考虑处理意外情况。这样一来,教学中费大力气讲授的异常处理机制,也因为暂时无用而被抛诸脑后。
本书则不纠缠于异常处理的细节和内建异常的类型,而是在讲述完基本语法后详细剖析一个程序实例(1.10.2节),展示如何分析和处理各种意外的输入情况,篇幅上也仅限制为一节。读者若能吃透这一部分内容,则当有编写健壮程序的意识,自能够在工作中举一反三,也无须笔者再行赘述。反之,若对健壮性不够重视,则多费篇幅也没有意义。
作为这种取舍思路的补充,本书有时会指出一些自学内容,将其留作练习,并引导读者进行思考或通过网络查阅相关资料。作为编程入门教科书,本书首要讲述程序设计的一般性方法,例如:
? 数据类型、流程控制、输入/输出和函数等基本手段;
? 状态机、递归、函数式编程等高级技巧;
? 数据结构和算法;
? 面向对象的设计思想。
对Python自身语法的介绍,也在本书各部分占据了相当篇幅。然而本书终归不是语法手册,所以并不追求语法知识细节的完整性。书中大部分小节后会给出延伸的问题和练习,或是明确的编码练习,或是要求读者进行深入地学习和思考,统称为思考和扩展练习。本书在设计和挑选例题时力图做到和传统的程序设计入门书籍在角度和深度上有所差异,目的在于为学生和教师提供更加开阔的思路。
计算机程序设计的理论基石(如语言基本模型、数据结构和算法)是在半个世纪前奠定的。虽然Python诞生的年代稍晚,但也基于这些基石构建而成。Python的主体部分是基于朴素平实的想法构建而成,而非天才的灵光一现。本书的一个重要初衷就是将这些朴素呈现给读者。笔者舍去了一些和该初衷无关的内容,如传统教学中往往着重介绍的字符串显示控制标记,在本书中只是一带而过。而那些更为深层次的基本概念则得到了强化,例如状态机模型、递归消除、面向对象动机及性能权衡等。
本书在示例中坚持给出完整可执行的代码或交互界面步骤,然而本书绝非手把手的教程。书中有些内容对于学习者来说是具有相当难度的,需要读者反复阅读思考并且动手实践才能够理解或掌握。这种难度是具有现实意义的:较难内容大多数来自于工程实践、后续学习,甚至是求职面试中的重点。读者应当认识到对这些问题的思考能力和思考过程的重要性。
内容编排
本书分为4章,取名为:
? 第1章 基础;
? 第2章 函数;
? 第3章 数据结构;
? 第4章 面向对象。
上述各章内容并非泾渭分明,原因主要在于Python的知识点存在许多循环依赖,如图1所示。例如for循环用到了迭代器的概念,而讲授迭代器需要足够的面向对象知识,绕过分支控制先完整地讲述面向对象也不现实。对于有经验的读者来说,这没有任何问题,但对初学者则会造成很大困扰。基于这些原因及教学实践,本书在第1章中简要讲授了函数定义而非拖至第2章,将定义类的基本方法提前至第2章而不是留待第4章。这两节内容的调整是本书的重要关节。
图1 知识点的循环依赖
这4章内容以第1章篇幅最长,第2、3章次之,第4章最短。程序的基本设计方法、异常处理和程序调试等内容归入了第1章。模块和迭代器归入了第2章。部分内建类型,如字典的深入讲解归入了第3章。在第4章面向对象设计部分,考虑到相应的学习阶段课时、Python的混合风格特性和简洁的面向对象语法,笔者决定精简篇幅而非长篇大论。另外,由于在Python中对象模型和面向对象调用风格的无处不在,许多相关知识已经散见于前3章,也没必要再次重复讲述。
习题
本书没有单独整理的习题集。首先是因为笔者水平所限,并且时间也有限,无法设计大量的原创习题。另一个原因是笔者反对采用在语言学习阶段使用刷题的方式提升编程能力①。读者如能将本书示例及每小节末尾的思考和扩展练习完成,在笔者看来就足够了。如果读者在完成这些内容后仍觉不足,不要把精力浪费在所谓的习题集或面试宝典上,而应该去学习更为深入的主题(如操作系统、网络、算法或编译原理等),或投身于解决实际问题。
参考文献
本书中提到的若干算法、观点、文档和源码的原始出处在书尾以参考文献的形式给出。阅读原始文献是非常有必要的。通过对这些文献的阅读,即便是少量阅读,学习者也能够体会到创造者当时的心境。这看似增加了额外的学习任务,但实为捷径。为了便于读者检索,笔者用[1][2]的编排格式给出了所对应的参考文献序号。
版本
笔者在Mac计算机上完成了绝大部分的写作工作。写作时的Python最新版本是3.7。当然这绝不意味着读者也需要搞一套这样的软硬件环境。使用Linux的读者不用太过担心兼容性问题。使用Windows系统的读者除去1.6.3节中管道行的相关命令外,应当可以顺利运行本书中的其他程序。笔者平时并不使用Windows系统,所以本书示例在Windows平台上可能会稍有更多的兼容性问题。但跨平台的兼容性带来的麻烦远不及Python本身升级带来的兼容性问题。所以在学习时纠结于应当使用哪种操作系统平台是意义不大的,因为Python未来的某次升级可能导致本书代码无法运行的情况更多。好在互联网的便利使得笔者对本书出版后做勘误和代码更新很容易,笔者会将本书的勘误信息和最新的升级信息反馈给出版社,读者可在出版社的官网上找到本书,获取这些资料。
格式约定
为了便于读者学习,本书坚持给出绝大多数示例的完整代码及运行效果。有的代码示例直接运行即可看到期望的结果,而有的代码则需要进行一些样例输入或者将其导入后调用。本书统一将这些运行结果或运行示例称为程序运行结果。
本书用以下格式表示代码实例。这些实例大部分能够直接运行,少部分需要读者自行补充完整。
本书用以下格式表示交互执行的过程和结果。
其中, $ 表示操作系统的终端(shell)提示符,>>>表示Python的交互式执行环境提示符。该格式还用来排版批量的文本,例如:
至于在说明文字中用到的解释性代码,则直接用如下格式排版:
本书的代码参考Python的推荐风格PEP-8,但有时为了行文紧凑也会缩减空格及空行。
获取配书资料
本书提供以下配书资料:
? 配套教学视频;
? 实例源代码文件;
? 教学PPT。
这些资料需要读者自行下载。请登录华章公司网站,在该网站上搜索到本书,然后单击资料下载按钮,即可在本书页面上找到下载链接。
读者对象
本书的最佳读者设定是有教师指导的程序设计初学者,笔者称之为教科书设定。这意味着本书不会教读者诸如安装执行环境和使用代码编辑器这类准备工作。这是教师的职责。如果读者是自学者,那么你应当首先确保自己正确地安装了Python运行环境,并尝试编辑一两个Python小程序运行一下。这在今天很容易,读者只需要随便找一个在线视频,看上二三十分钟即可。对于自学者来说,找到几位Python的使用者去获取一些初始建议,并且能够在学习遇到困惑时求助也是非常重要的。很多人在学习过程中因为某些不经意的障碍而放弃。比如原本代码写对了,但某个执行路径不对,在反复检查代码后依然失败而信心全无。
本书还特别适合一类读者,即学过一些程序设计语言的粗浅知识,马马虎虎地写过一些程序,处于某种目的又希望认真、正式地学习程序设计的学生。他们有可能是打算大学毕业希望找一份IT工程师工作的学生,也可能是中学阶段学过一些编程后希望在这条路上走得更远的学生。对这类读者来说,本书将带给他们更加深厚的基础能力。
致谢
本书的写作得到了好友姜寒先生的大力协助。姜先生有丰富的实践经验,又兼通各种主流程序设计语言。笔者在写作本书时多有疑难困阻,或关于Python本身,或关于其他广泛主题;又有时在详略取舍上难以决断,或是对一些观点信心不足。每每及此,与姜先生讨论后总能破除心中所障。除此之外,姜先生还审阅了本书的部分章节,从内容到行文,均提出了宝贵意见。
张頔于北京