计算机诞生至今不过六七十年,但它已经改变了世界,改变了每个人的生活。人们每天都在与计算机交流(如智能手机),各领域专业人员的大量日常工作都需要使用计算机,从事与计算机相关工作的人们已经发展为社会上最大的专业技术社团。计算机的研究和应用、互联网和其他相关领域,还在不断呼唤大量熟悉计算机的专业开发人才。计算机科学技术的开发和应用能力已被广泛认为是国家竞争力的重要组成部分。因此,学习计算机科学技术知识,不仅是社会发展的需要,而且已成为个人的重要职业竞争力。然而,要深入理解计算和计算机,使其成为得心应手的工具,就必须学习编程。
近年来,python语言的良好特征已经得到学界和业界的广泛认可,被世界上许多知名大学选作计算机科学教育的第一门语言,也被很多企业和实际项目作为开发语言。这些发展情况,使越来越多的人有了学习python的兴趣和需要。
本书源自作者讲授基于python的编程课程的经验,又经过认真整理,目标是提供一条清晰易行的学习路径。本书的结构和内容力图反映编程的本质,可以作为高校计算机基础课程教材,也适合希望学习python语言和编程技术的读者阅读和参考。本书书名反映了作者对编程的基本认识:编程是从要解决的问题开始,最终得到解决问题的程序的过程。要学好编程,就要努力去理解这个过程,还必须反复实践。
编程就是为了指挥计算机(而不是我们自己),通过一个自动计算过程(而不是人的操作)去解决问题。为了指挥计算机工作,我们需要理解计算机,理解计算过程,理解指挥计算机完成计算的途径和方法。还需要一种计算机能处理的表达方式,也就是编程语言(或称程序设计语言,本书中用python),用于说明计算机应该怎样工作。
程序是人写出的一段文字,表达的是要求计算机完成的一个计算过程。完成编程工作需要多方面的理解。首先需要理解面对的问题:它究竟是什么、要求做什么、可能用什么方法和计算过程去解决?要理解自己写出的程序,理解它描述的计算过程。最后的理解也非常重要:理解两者之间的关系,即自己的程序是否正确解决了相应的问题?没有对问题和程序的深入思考和理解,就不可能开发出好的、功能正确的程序。
学习编程时必须关注两方面的问题:如何从一个解决问题的需求出发,逐步开发出一个计算过程;如何使用编程语言(如python)正确地写出解决问题的程序,描述(实现)这个计算过程。本书的做法是提出一个个问题,从简单到复杂,讨论从它们出发的程序开发过程:分析问题的细节,设法将其严格化,提出可能的解决方案,再经分解和设计,以及随后的编码和调试,最终开发出一个程序。完成了一个程序,常常不是工作的结束,还需要回过头去考察这个程序,分析其优点和缺点,研究改进或变化的可能性。这样的程序开发过程和其中的分析、思考、选择、决策等,反映了编程工作的本质和正确工作方法。当然,考虑到读者的经验积累,较前章节中的讨论包含了更多细节,后面逐渐简化,可能只关注工作中的一些要点。但是实际上,对任何一个问题,无论简单或复杂,上述的思考和工作过程都会再一次重复。只不过随着读者的经验积累,一些问题的分析和决策变得愈发自然顺畅,以至于其明显性逐步减弱。这种趋势也反映了读者的进步。
在阅读本书的过程中,建议读者去亲身体验程序的开发过程:看到一个问题之后,最好先不去看书中的分析和解决方法,而是自己思考,设法解决这个问题,完成之后再与书中的做法比较。如果两种做法不同,就应该分析它们各自的长处和短处。采用这样的方法学习本书(和编程),读者将不再是被动的接受者,而是主动参与者。
实际上,对每个问题,都可能有很多(理论上是无穷多)不同解决方法,对不同方法和设计的比较、选择和决策,也是编程工作中最重要的内容。对一个具体问题,总可能做出很多正确程序。如果问题稍微复杂,常能做出一组程序,其中任何一个都不比别的程序“更好”。这些情况说明,在编程学习中,并没有必须背诵的标准答案。当然,另一方面,作者也希望通过书中实例,反映良好的编程工作和好程序的特征。书中程序都由作者开发(其间也参考了许多材料),并经过仔细修改和运行试验。程序的格式符合python社团的考虑,结构良好,实现方法清晰简洁,可以作为读者参考的范例。
编程语言是编程的工具,也是人与计算机交流的工具。它既要反映思维的特点,使人易于使用,也要反映计算机的特点,使计算机能按它写出的程序高效工作。python被广泛认为是一种比较适合初学者的语言,其设计较好地反映了计算机和编程的性质和特点,具有比较平滑的学习曲线。最简单的python程序可以看作数学和算术的自然延续,可以方便地运行,立刻看到结果(或效果)。初学者可以从这里开始一步步深入,在解决越来越复杂的问题的过程中,逐渐领悟编程和计算的性质和本质。另一方面,python也支持许多高级编程概念,从高阶函数、生成器函数,到复杂数据对象的描述式、面向对象的编程等,反映了现代编程技术和需求的发展。本书中详细介绍了这些机制和技术,最后还介绍了两个重要的、有很强实际意义的编程问题:图形用户界面编程和并发编程。由于python既容易入门又支持许多高级编程概念,因此是学习编程和计算的很好选择。
本书的主要特点有:首先是包含了对许多问题的深入讨论,既有针对具体编程问题的讨论,也有结合具体问题而展开的一般性讨论。具体到编程和python语言,本书通过实例介绍了大量重要的概念和技术,其中有些专门针对python语言,更多概念和技术具有一般性。书中还介绍了python语言的一些重要细节和工作原理,以帮助读者深入理解python程序,在编程中做出正确的设计选择。
本书包含八章和若干附录,下面简单介绍它们的情况:
第1章介绍一些基本情况。这里主要讨论计算机和程序的关系,程序设计的基本问题,python语言的历史、现状和应用情况,还概述了基本的程序开发过程。
第2章是计算和编程入门。这一章首先介绍简单的数值表达式的描述和求值、类型的概念和意义、数学函数包的使用、字符串的概念和基本运算。然后讨论变量和赋值、顺序计算的脚本程序、条件控制(if语句)、重复计算和循环(for和while语句),最后讨论了函数的概念、意义,以及基本的函数定义技术。
第3章集中讨论基本的编程技术。其中首先讨论循环的开发和实现、输入控制的循环等,然后介绍函数定义的递归方法、递归和循环的关系,最后集中讨论定义函数的思路和技术。这一章还介绍了一些与所有程序都有关的重要概念和问题,包括程序运行时间和计时、程序中的断言、循环不变式、程序正确性问题、程序的终止性等。
第4章讨论python函数定义、程序结构和编程中的调试问题。这里首先介绍与程序的结构和行为有关的一些基本问题,包括作用域、状态和环境的概念,程序执行中环境和状态的变化,模块的执行和导入等。然后介绍python函数定义的结构、函数的执行和python丰富的函数参数机制,并介绍了以函数为参数的高阶函数、lambda表达式等。最后集中讨论程序的测试和调试,以及idle支持程序调试的功能。
第5章讨论复杂数据的组织和python的组合数据类型。这里首先讨论了表、元组、字符串及其在程序中的使用,然后从序列的概念出发,统一地介绍了序列的构造技术和各种序列操作。随后介绍了字典和集合,以及这两种组合类型在程序中的应用。这一章还讨论了对象的变动性问题,介绍了字符串的格式化功能,详细解释了逻辑判断和逻辑表达式的求值过程,并对python函数的参数问题做了总结。
第6章介绍一些深入的编程技术。这里首先讨论文件的概念和文件使用技术,并介绍了两种重要的函数技术:生成器函数和闭包。然后讨论错误处理问题和python处理异常的结构。最后介绍了数据持久性问题,以及python标准库支持持久性的pickle包。
第7章集中讨论面向对象的编程和python的相关机制。这里首先介绍了类和对象的概念,类定义的基本技术和基于类的程序开发。然后讨论了类继承和派生类的定义,以及多继承问题等。这一章的最后介绍了python的特殊方法名,以及利用它们模拟容器、迭代器、上下文管理器等的技术,还介绍了with语句的意义和应用。
第8章讨论两个重要的编程问题。首先介绍图形用户界面(gui)编程的问题,以及基于标准库包tkinter的gui编程技术。然后介绍并发编程的问题,以及基于标准库包threading的并发编程。这两部分都包含许多实例,还说明了在实际应用开发中使用这些技术时需要解决的一些问题和处理方法。
本书的附录包括python语言速查手册、标准函数表、书中使用的几个标准库包的简单介绍,以及idle开发环境的命令简介。
本书各章后附有很多习题,供使用本书开设课程的教师和自学的读者参考。某些章的最后有一节 “补充材料”,其中介绍一些与该章内容有关但比较具体或初学阶段不常用的python语言机制,有时还总结了该章中讨论的一些编程技术。有几章中的若干节被标以星号,它们或者是技术性较强,或者内容涉及较深入的问题,作为基础课程的教学或者自学者初学时,可以跳过这些部分,留待课下或以后阅读。
作者在北京大学数学学院讲授相关课程时,与参加学习的同学有很多讨论,这些讨论帮助作者澄清了很多重要问题。参与课程辅导工作的胡婷婷和陈晨以及刘海洋,都提出了一些很好的建议。在本书的成书过程中,机械工业出版社的朱劼编辑非常认真,提出了很多改进意见。对所有这些帮助,作者在此一并表示衷心感谢。最后,作者希望得到读者的意见和反馈,并先在这里表示感谢。
裘宗燕
2017年3月
[第1章 程序设计和python
1.1.1 “是什么”和“怎样做”的知识
1.1.2 计算和程序
1.1.3 编程语言
<a href="https://yq.aliyun.com/articles/117573/">1.2 python语言简介</a>
1.2.1 python语言的发展和应用
1.2.2 python系统和idle编程环境
<a href="https://yq.aliyun.com/articles/117586/">1.3 程序开发</a>
1.3.1 程序开发过程
1.3.2 程序错误
1.3.3 从问题到程序
<a href="https://yq.aliyun.com/articles/117590/">练习</a>
[第2章 计算和编程初步
2.1.1 整数计算
2.1.2 浮点数和复数
<a href="https://yq.aliyun.com/articles/117635/">2.2 数据对象、计算和类型</a>
2.2.1 对象和类型
2.2.2 混合类型计算和类型转换
2.2.3 数值类型和计算的简单总结
<a href="https://yq.aliyun.com/articles/117643/">2.3 内置函数和数学函数包</a>
2.3.1 函数及其使用
2.3.2 处理数值的内置函数
2.3.3 数学函数包
<a href="https://yq.aliyun.com/articles/117653/">2.4 字符串</a>
2.4.1 字符串和字符串类型
2.4.2 字符串操作
<a href="https://yq.aliyun.com/articles/117674/">2.5 标识符、变量和赋值</a>
2.5.1 变量、名字和值
2.5.2 简单顺序计算
<a href="https://yq.aliyun.com/articles/117694/">2.6 简单脚本程序</a>
2.6.1 脚本的编辑和执行
2.6.2 程序和输入
<a href="https://yq.aliyun.com/articles/117706/">2.7 判断和条件控制</a>
2.7.1 条件判断和逻辑表达式
2.7.2 if语句(条件语句)
2.7.3 编程实例
<a href="https://yq.aliyun.com/articles/117736/">2.8 重复计算和循环</a>
2.8.1 重复计算
2.8.2 for语句和重复计算
2.8.3 while语句和迭代
2.8.4 循环控制
<a href="https://yq.aliyun.com/articles/117758/">2.9 计算的抽象和函数</a>
2.9.1 计算的控制和抽象
2.9.2 计算的抽象:函数
2.9.3 函数定义和使用实例
<a href="https://yq.aliyun.com/articles/117768/">2.10 若干python机制及其他</a>
2.10.1 已讨论的python机制
2.10.2 若干python机制
2.10.3 python解释器
<a href="https://yq.aliyun.com/articles/117784/">2.11 补充材料</a>
2.11.1 语言细节
2.11.2 编程技术
<a href="https://yq.aliyun.com/articles/117790/">练习</a>
[第3章 基本编程技术
3.1.1 循环的需求和问题
3.1.2 常见循环形式
3.1.3 输入循环
<a href="https://yq.aliyun.com/articles/117806/">3.2 递归</a>
3.2.1 递归定义的函数
3.2.2 乘幂的计算
3.2.3 循环和递归
3.2.4 斐波那契数列的计算
3.2.5 最大公约数
3.2.6 不容易用循环求解的递归问题
3.2.7 更复杂的递归情况
<a href="https://yq.aliyun.com/articles/117807/">3.3 程序终止性</a>
3.3.1 调和级数的部分和
3.3.2 程序终止性不可判定
<a href="https://yq.aliyun.com/articles/117811/">3.4 定义函数</a>
3.4.1 为什么定义函数
3.4.2 学习定义函数
3.4.3 函数:两种观点及其联系
3.4.4 通用和专用的方法
<a href="https://yq.aliyun.com/articles/117813/">练习</a>