书名:计算思维与Python编程
ISBN:978-7-115-53221-3
本书由人民邮电出版社发行数字版。版权所有,侵权必究。
您购买的人民邮电出版社电子书仅供您个人使用,未经授权,不得以任何方式复制和传播本书内容。
我们愿意相信读者具有这样的良知和觉悟,与我们共同保护知识产权。
如果购买者有侵权行为,我们可能对该用户实施包括但不限于关闭该帐号等维权措施,并可能追究法律责任。
著 [美] 玛丽亚·利特文(Maria Litvin)
[美] 加里·利特文(Gary Litvin)
译 王海鹏
责任编辑 陈冀康
人民邮电出版社出版发行 北京市丰台区成寿寺路11号
邮编 100164 电子邮件 315@ptpress.com.cn
网址 http://www.ptpress.com.cn
读者服务热线:(010)81055410
反盗版热线:(010)81055315
Original English language edition, entitled Coding in Python and Elements of Discrete Mathematics by Maria Litvin and Gary Litvin.
Copyright © 2019 by Maria Litvin and Gary Litvin.
Simplified Chinese-language edition copyright © 2020 by Posts & Telecom Press. All rights reserved.
本书中文简体字版由作者Maria Litvin和Gary Litvin授权人民邮电出版社独家出版。未经出版者书面许可,不得以任何方式复制本书内容。
版权所有,侵权必究。
本书以教授精确的计算思维为目标。全书共18章。首先介绍了Python编程的基础知识,包括变量和算术计算、集合与函数、循环、字符串、列表、字典、海龟绘图、序列等知识;然后深入介绍了专门的数学知识,包括奇偶校验、计数、概率、向量和矩阵、递归、图、数论和密码学,并且结合Python编程来解决各个领域中的特定问题。附录部分给出了Python编程相关参考资料。
本书适合作为计算机相关专业的Python程序设计和计算思维的课程教材,也适合想要学习计算思维和Python编程的读者包括中学生阅读参考。
玛丽亚 · 利特文(Maria Litvin)自1987年以来一直在马萨诸塞州安多弗(Andover)的菲利普斯学院(Phillips Academy)教授计算机科学和数学。在加入菲利普斯学院之前,Maria在波士顿大学教授计算机科学。玛丽亚与人合著了几本受欢迎的计算机科学教材—— C++ for You++:An Introduction to Programming and Computer Science(1998)、Java Methods:ObjectOriented Programming and Data Structures(2001-2015)、Be Prepared for the AP Computer Science Exam in Java和250 Multiple-Choice Computer Science Questions,并参与组织了针对中小学生的大陆数学联盟(Continental Mathematics League,CML)计算机科学竞赛。作为大学委员会(College Board)的顾问,玛丽亚为高中AP计算机科学教师提供培训。自2014年以来,作为Code.org的推动者,玛丽亚已经培训了数百名新英格兰的小学教师,他们为K-5级儿童教授计算机科学。玛丽亚获得了1999年西门子新英格兰数学、科学和技术先进奖,以及2003年RadioShack国家教师奖。
加里 · 利特文(Gary Litvin)是C++ for You++、Java Methods:Be Prepared for the AP Computer Science Exam in Java、250 MC Questions的合著者和CML计算机科学竞赛的共同参与者。加里曾在软件开发的许多领域工作过,包括人工智能、模式识别、计算机图形学和神经网络。作为Skylight Software公司的创始人,他开发的SKYLIGHTS/GX是C和C ++程序员最早使用的可视化编程工具之一。加里领导开发了多种先进的软件产品,包括交互式触摸屏开发工具、光学字符识别(OCR)和手写字符识别系统、信用卡欺诈检测软件等。
献给Henry和Esther,数字世界的原住民
本书是我们早期的Mathematics for the Digital Age and Programming in Python一书的 “更早讲Python”的版本。在本书中,我们更早地介绍了Python特性,为读者提供了必要的工具,使读者可以更快地以更加“Python式(pythonic)”的惯用方式,开始编写Python代码。在本书中,我们增加了两章(“第9章 海龟绘图”和“第14章 向量和矩阵”),以及介绍斐波那契数列的一节(“第10章 序列与和”的10.5节);更新了许多示例、练习和解答;更改了标题,从而更好地匹配这一系列主题和快速变化的技术环境与词汇。
但这本书的主要理念仍然没有改变:介绍离散数学概念和思维,我们认为这些概念是所有有基础的编程人员的基本知识。这种数学知识很容易学习,但美国大多数中小学数学课程还没有包括离散数学的内容。本书的数学部分包括许多动手编程练习,这些练习可以强化学生对编程和数学的认识。
“那么,这是一本数学书还是一本计算机编程书?”这可能是心急的读者心中的第一个问题。但为什么必须选择呢?这是图书管理员的困境:“它是属于数学类还是计算机类?”有一个简单的解决方案:在每类书架上各放一本。
本书的目的是教授一种特定的思维方式——精确思维,以及如何解决需要这种思维方式的问题。数学和计算机编程都能培养精确思维的能力,并解决那些需要精确解的问题。
数学教会我们欣赏严谨论证的美。从长远来看,这比解决当前实际问题的课程更有价值。数学并不是存在于真空中的——它的抽象植根于几个世纪以来积累的实践知识。数学教学借鉴了我们周围世界的例子和类比,至少它应该如此。然而,我们周围的世界变化得越来越快。在过去的五六十年间,我们的世界变得数字化了。这种变化如此深刻,以至于人们有时难以完全理解。我们的中小学数学课程在很大程度上忽略了这种变化,这是否就是人们难以理解这种变化的原因?
如果我们能够造出“时间机器”,让欧几里得穿越时空来到现代化的世界,他会觉得很欣慰,因为在现代技术的浪潮中,他熟悉的几何学仍然在学校里教授。“老对手”牛顿和莱布尼茨都会感到非常满意,因为成千上万的美国高二和高三学生正在学习如何求导和使用积分。但是,离现在不远的乔治·布尔(George Boole),尽管他的名字在每一种现代计算机编程语言中都是不朽的,但他仍然需要搜寻几十本教材才能找到他提出的代数。至于约翰·冯·诺依曼(John von Neumann),这位才华横溢的数学家,也是计算机技术的先驱之一……好吧,按照他一贯的乐观态度,他会预测在20年左右的时间里,每个小学生都会学习与门、或门和非门。但是,为什么事实不是如此呢?
在本书中,我们汇集了一些与数字世界相关的更容易理解的数学主题。其中许多主题,通常在大学新生课程中以“离散数学”之名讲授。离散数学已成为所有基础数学的代名词,但在标准的初中和高中代数、微积分初步和微积分课程中,这种数学都被忽略了。在20世纪70年代,唐纳德·克努特(Donald Knuth)和他在斯坦福大学的同事创造了“具体数学”这一名词(融合了连续数学和离散数学,并且也很具体,不是太抽象),来描述克努特在斯坦福大学教授的课程。后来,“具体数学”成为了他们的一本阅读起来很愉快的书的标题[1]。正如他们在序言中解释的那样,克努特“发现他的技能中缺少一些数学工具,他需要一些数学工具,以便对计算机程序有彻底的、充分的理解,这些数学工具与他在大学里作为数学专业学生所学的东西完全不同”。
因此,如果你对计算机编程感兴趣,我们希望本书能让你成为更好的计算机程序员。如果你对数学更感兴趣,你将有充分的机会解决有趣的问题,并在计算机程序中,对其中的一些问题进行建模。你将熟悉通常初中生和高中生不会接触到的有趣的数学;你将学会解决真实问题(即你事先并不知道如何解决的问题);你将感受到数学推理和证明的力量。作为奖励,你将获得Python(一种流行的经济有效的编程语言)编程的实用技能。
我们选择Python有几个原因。首先,Python让你有机会在交互式环境中,通过即时反馈来体验该语言。其次,Python的语法并不太复杂。再次,Python具有简单但强大的功能,可用于处理列表和“字典”(映射)。最后,Python易于安装和使用,它是免费的。当然,还有其他编程语言具有类似的属性,可以满足我们的需求。归根结底,重要的不是特定的编程语言,而是能够精确地思考数学知识和计算机程序。
本书得益于计算机科学和数学界的许多朋友和同行的帮助及精到见解。
我们要特别感谢北野山高中(Northfield Mount Hermon High School)的Abby Ross,他仔细阅读了整本书,并提出了许多有价值的更正意见和建议。穆罕默德王子大学(Prince Mohammad Bin Fahd University)的Patricia M. Davies博士是自本书早期版本以来的支持者,他仔细阅读了这个版本(即本书),并提供了许多有用的修订建议。尼达姆高中(Needham High School)的Hans Batra也提供了有用的建议。
本书之前的版本得到了很多朋友的帮助,包括J. Adrian Zimmer博士(俄克拉荷马科学与数学学院)和Kenneth S. Oliver(以前在康涅狄格州伍德布里奇的Amity Regional高中)。时任南卡罗来纳大学哥伦比亚分校计算机科学与工程系主任的Duncan A. Buell教授阅读了全部草稿,提出了许多改进建议,尤其是关于“第18章 数论和密码学”。
我们感谢Henry Garden对编写教材的方法的建议,感谢Margaret Litvin帮助校对。和往常一样,我们最感谢玛丽亚的数学和计算机科学专业的学生,他们测试了本书的编程练习,做了很多很好的修正,并用他们的热情鼓舞了我们。
玛丽亚·利特文(Maria Litvin)
加里·利特文(Gary Litvin)
[1] Ronald L. Graham, Donald E. Knuth, Oren Patashnik, Concrete Mathematics: A Foundation for Computer Science, Second Edition, Addison-Wesley, 1998.
本书由异步社区出品,社区(https://www.epubit.com/)为您提供相关资源和后续服务。
本书提供如下资源:
本书源代码;
书中彩图文件。
要获得以上配套资源,请在异步社区本书页面中单击,跳转到下载界面,按提示进行操作即可。注意:为保证购书读者的权益,该操作会给出相关提示,要求输入提取码进行验证。
如果您是教师,希望获得教学配套资源,请在社区本书页面中直接联系本书的责任编辑,或发送邮件至contact@eputit.com.cn索取。
作者和编辑尽最大努力来确保书中内容的准确性,但难免会存在疏漏。欢迎您将发现的问题反馈给我们,帮助我们提升图书的质量。
当您发现错误时,请登录异步社区,按书名搜索,进入本书页面,单击“提交勘误”,输入勘误信息,单击“提交”按钮即可。本书的作者和编辑会对您提交的勘误进行审核,确认并接受后,您将获赠异步社区的100积分。积分可用于在异步社区兑换优惠券、样书或奖品。
我们的联系邮箱是contact@epubit.com.cn。
如果您对本书有任何疑问或建议,请您发邮件给我们,并请在邮件标题中注明本书书名,以便我们更高效地做出反馈。
如果您有兴趣出版图书、录制教学视频,或者参与图书翻译、技术审校等工作,可以发邮件给我们;有意出版图书的作者也可以到异步社区在线提交投稿(直接访问www.epubit.com/selfpublish/submission即可)。
如果您是学校、培训机构或企业,想批量购买本书或异步社区出版的其他图书,也可以发邮件给我们。
如果您在网上发现有针对异步社区出品图书的各种形式的盗版行为,包括对图书全部或部分内容的非授权传播,请您将怀疑有侵权行为的链接发邮件给我们。您的这一举动是对作者权益的保护,也是我们持续为您提供有价值的内容的动力之源。
“异步社区”是人民邮电出版社旗下IT专业图书社区,致力于出版精品IT技术图书和相关学习产品,为作译者提供优质出版服务。异步社区创办于2015年8月,提供大量精品IT技术图书和电子书,以及高品质技术文章和视频课程。更多详情请访问异步社区官网https://www.epubit.com。
“异步图书”是由异步社区编辑团队策划出版的精品IT专业图书的品牌,依托于人民邮电出版社近30年的计算机图书出版积累和专业编辑团队,相关图书在封面上印有异步图书的LOGO。异步图书的出版领域包括软件开发、大数据、AI、测试、前端、网络技术等。
异步社区
微信服务号
本书的配套教学资源包括学生练习文件、Python入门知识(附录A)、勘误表、补充论文和教学大纲,以及针对教师的技术支持信息。
PY指的是本书的学生文件或教师文件。例如,书中的“参见PY\PythonCode\Fibonacci.py”表示位于StudentFiles(或TeacherFiles)的PythonCode文件夹中的Fibonacci.py文件。
▼▲ 像这样的书边缘的箭头括号,标记了一些补充材料,针对那些更好奇的读者。这些材料可以让你对后续章节的内容有所了解,或补充技术细节。
■和◆ 在练习中,黑色正方形表示“中级”难度的题目,可能需要更多的思考或工作,而不是“简单”的问题或练习。黑色菱形表示 “高级”难度的题目,可能是探索式的问题、工作量较大的问题,或者未曾探索过的领域的问题。
✔ 练习中问题末尾的打勾标记表示答案或解答包含在学生文件中。我们已经为大约一半的练习提供了答案和解答。
教师文件包含所有练习和实验的完整解答,可提供给使用本书作为教科书的在校教师。
对于普通计算机用户来说,计算机程序或应用程序来自因特网或光盘(CD),然后在计算机或智能手机上运行。对于计算机程序员来说,程序是计算机执行的一组指令,用来完成精确定义的任务。实际上,计算机编程不仅是用特定的编程语言(如Python)“编写”这些指令。它涉及许多技能,包括设计软件、设计“算法”、设计“用户界面”(窗口、命令、菜单、工具栏等)、编写并测试代码,以及与软件用户交流互动等。
在本章中,我们将介绍计算机硬件的基本特性,解释编译器和解释器之间的区别,并展示如何使用Python的IDLE开发环境。
计算机的核心是中央处理器(CPU)。在个人计算机中,CPU是由微小的硅芯片制成的微处理器。该芯片上刻有数百万个晶体管。晶体管是一种微型数字开关:它控制信号的两种状态,“开”或“关”,即“1”或“0”。微处理器由小于1平方英寸的陶瓷外壳保护,安装在印制电路板(也称为主板)上。主板上还有内存芯片,以及用于连接其他设备的端口(见图1-1)。
图1-1 树莓派3 B型单板计算机,放在3.5平方英寸×2.25平方英寸的印制电路板上
计算机存储器是一系列统一的存储单元,这些单元称为“字节”。
1字节保存8位信息。
1位是最小的信息存储单元:“1”或“0”,“真”或“假”,“开”或“关”。
CPU可以按任意顺序访问内存中的字节。这就是计算机内存被称为“随机存取存储器(RAM)”的原因。同样的内存用于存储不同类型的信息:数字、字母、声音、图像、程序等。这些信息,必须以某种方式编码为0和1的序列。
2019年生产的典型个人计算机具有8GB(千兆字节)的RAM。
1 K字节(KB)= 1024字节 = 210字节,大约一千字节。
1 M字节(MB,“兆”)= 1024 K字节 = 220字节= 1,048,576字节,大约一百万字节。
1 G字节(GB,“吉”)= 1024 M字节 = 230字节 = 1,073,741,824字节,大约10亿字节。
1 T字节(TB)= 1024 G字节 = 240字节。
1 P字节(PB)= 1024 T字节 = 250字节。
一页有500~600个单词的文本,没有图片或特殊格式,大约需要3KB的存储空间;一张高分辨率照片可能需要2~3MB的存储空间,而1GB存储空间可以压缩的MP4格式保存数小时的视频。
CPU解释并执行存储在RAM中的指令。CPU获取下一条指令,解释它的操作代码,并执行适当的操作。有些指令用于算术和逻辑运算,有些用于将字节从一个位置复制到另一个位置,还有一些用于改变指令的执行顺序。除非特定指令告诉CPU“跳转”到程序中的另一个位置,否则指令将按顺序执行。“条件分支”指令告诉CPU继续下一条指令或跳转到另一个位置,具体情况取决于前一操作的结果。
以上这些操作都以惊人的速度发生。现代CPU以几GHz的速度运行,每条指令需要一个或几个时钟周期。
▼
为了更好地了解CPU指令及其执行方式,让我们来看看“汇编语言”,这是一种低级计算机语言。它是你所听过的现代语言的基础,如C++、Java、JavaScript和Python。
图1-2展示了一个非常短的汇编语言程序,用于8088微处理器(在20世纪80年代早期用于最初的IBM PC),其中包含相应指令的十六进制代码(十六进制系统在第6章中解释)和我们的注释。汇编语言代码非常接近实际的机器代码,但它允许你使用名称而不是数字,来表示指令和内存位置。
CPU有几个内置存储器单元,称为寄存器。图1-2中的代码使用的两个寄存器,称为AX
和BX
。例如,第一条代码(MOV BX, 0000
)将0移入BX
寄存器。
图1-2 一段8088汇编语言代码
我们将它留给你作为练习(练习题6),请弄清楚这段代码计算的内容。结果存储在BX寄存器中。
计算机代码中的错误称为“缺陷(bug)”,消除程序错误的过程称为“调试(debug)”。
图1-2中的代码是在一个名为debug的程序的帮助下生成的,该程序随MS-DOS操作系统和早期版本的Windows一起提供。调试程序允许程序员以受控方式逐步执行程序,并在每一步检查内存的内容。在程序未按预期工作时,使用调试程序可以帮助发现错误。
1.找到一台废弃的台式计算机,确保已拔下电源线,然后取下机箱盖(或在网上查找打开机箱的台式PC的高分辨率图片)。识别主板、CPU和内存芯片,识别计算机的其他组件:电源、硬盘、CD ROM驱动器。
2.计算机内存称为RAM,因为: ✔
(A)它提供对数据的快速访问
(B)它安装在主板上
(C)它以兆字节为单位
(D)它的字节可以按随机顺序寻址
(E)它的芯片安装在矩形阵列中
3.我的旧PC有512 MB的RAM和120 GB的硬盘,硬盘存储空间是RAM的多少倍?✔
4.可以用2位编码多少个不同的值?3位呢?1字节呢?
5.ASCII码表示在典型的美式键盘上可以找到的英文字母、数字和其他字符的大写和小写字母。每个字符以相同的位数编码。每个字符1字节是否足以表示所有这些字符?每个字符所需的最小位数是多少? ✔
6.◆在执行图1-2中的程序段后,解释AX
和BX
寄存器的内容。这段代码计算了什么? »提示:十六进制的15是十进制的21。« ✔
以数字序列的方式来编写程序是非常烦琐的(尽管在计算机时代的早期阶段,程序员就是这么做的)。幸运的是,人们很快意识到,他们可以为编写程序而定义特殊的语言,并使用计算机将程序从高级编程语言转换为机器代码。早期的编程语言有Fortran、COBOL和BASIC。今天流行的语言有C++、C#、Java和JavaScript等。Python是另一种非常流行的编程语言:它是由荷兰数学中心(Stichting Mathematisch Centrum)的Guido van Rossum于20世纪90年代初发明的。[1]
在高级编程语言中,每个语句都转换为多个CPU指令。图1-3展示了一个用Python编写的函数,它由一个文档字符串(Docstring,三引号中的一段注释,帮助使用该函数)和一些语句组成。
图1-3 用Python编写的函数
用机器语言或汇编语言编写的程序仅适用于具有兼容性CPU的计算机。换句话说,命令/语句限定于特定的CPU。用高级语言编写的程序可以与任何CPU一起使用。例如,它可以在PC或Mac上运行。
✦ ✦ ✦
有两种方法,可以将高级编程语言编写的程序转换为机器代码。第一种方法称为“编译”:一种称为“编译器”的特殊程序,检查高级语言编写的程序文本,生成适当的机器语言指令,并将它们保存在一个可执行文件中,该文件可以在计算机上运行。程序编译后,运行该文件就不需要编译器了。第二种方法称为“解释”:一种称为“解释器”的特殊程序,检查程序的文本,生成适当的指令,并立即执行这些指令。解释器不会创建可执行文件,每次运行程序都需要解释器。
编译就像外语教材的书面翻译一样,解释就像在外国人说话的同时进行同声翻译。解释器可以从文件中读取程序,也可以允许你以交互方式逐行输入程序语句。
一些现代语言(如Java)使用混合的方法。首先,它们将程序编译成一种称为“字节码”的中间低级语言,它仍然独立于特定的CPU,但更紧凑,更接近机器语言。然后它们在解释字节码时执行程序。Python也将“模块(函数库)”预编译为字节码。
✦ ✦ ✦
程序的文本由相当严格的语法规则控制:你不能简单地输入随心所欲的内容,并指望计算机理解它。
程序中的每个符号都必须位于正确的位置。
在英语或其他自然语言中,你可以拼错一个单词或省略一些标点符号,但仍然可以生成可读的文本。这是因为自然语言具有“冗余”,信息以低于最佳效率的方式传输,但这导致即使它有某种乱码,读者仍可以正确地解释消息(见图1-4)。
图1-4 Lyla Fletcher Groom的故事,5岁
(由写作研讨会提供)
编程语言实际上没有冗余,几乎每个字符都是必不可少的。编程中很可能会犯错误,因此编程人员必须学会耐心并注重细节,在修复代码的错误时坚持不懈。
✦ ✦ ✦
我们现在准备使用Python。根据开源许可证,Python可免费获得,即使是商业应用程序也是如此。Python许可证由Python Software Foundation管理。
在本书中,我们将使用Python 3,即Python的较新版本。
▼
早期版本的Python称为“Python 2”。Python 2和Python 3之间存在一些差异——它们不是百分之百兼容。在撰写本书时,Python 3的最新版本是3.7.3。
关于如何下载适用于你的计算机和操作系统的Python安装程序,请参阅其他相关入门教程。
▲
✦ ✦ ✦
在编译语言时,你需要创建程序文本,并将它保存在一个文件中,称为“源代码”,然后让源代码文件通过编译器运行,以得到可执行程序。在Python中,你可以从源文件中读取程序,也可以在Python解释器Shell中输入单个语句,并立即查看结果。
使用GUI(图形用户界面)前端运行Python解释器很方便。标准安装的Python附带的GUI称为IDLE(见图1-5)。
图1-5 在Windows系统中,Python的GUI“Shell”,称为IDLE
>>>是Python解释器的“提示符”。提示符是来自程序的信号,表示它正在等待用户输入。用户可以输入语句,当用户按<Enter>键时,解释器会显示结果。
例如,输入:
>>> 2+3 <Enter>
(用户输入以粗体显示)。Python会显示:
5
>>>
看起来很不错!这里发生了很多事情。解释器读取你输入的文本行(语句),然后分析文本并发现该语句有两个用+号分隔的数字。分析文本并提取它的组件的过程称为“解析”。
一些小实验会让你相信空格并不重要(只要语句在提示后立即开始,没有前导空格)。例如,你可以输入2 + 3
或2 + 3
或2 + 3
——结果相同。但是如果你输入2 + * 3
,你就会得到:
>>> 2+*3
^
SyntaxError: invalid syntax
>>>
现在尝试:
>>> 2(3+4)
你预期会得到14,对吗?没有!你得到的是:
Traceback (most recent call last):
File "<pyshell#4>", line 1, in <module>
2(3+4)
TypeError: 'int' object is not callable
显然,Python解释器“认为”你输入的语句有问题。但是,Python(让我们将解释器简称为Python)不是报告语法错误,而是报告了别的内容,这似乎没有什么帮助。TypeError
指的是一个对象的“类型”(一个整数、一个函数等),而不是你在键盘上输入的内容。显然Python已经断定你试图用一个名为2
的函数调用输入值3 + 4
,所以Python告诉你(以它自己神秘的方式),2
不是一个函数。你可能会认为Python有时非常愚蠢。事实上,它既不聪明也不愚蠢——它只是一段代码。
同时,你真正的意思是:
>>> 2*(3+4)
也许你认为乘法符号是可省略的,就像在数学中一样。不是这样。正如我们告诉过你:每个字符都很重要!
1.定义“冗余”。✔
2.在Python解释器中输入2 + −3
。这是有效的语法吗?解释结果。现在对2 ++ 3
做同样的事情。
3.■尝试2 +++ 3
。解释结果。
4.尝试2 ** 3
和2 ** 4
。Python的运算符**表示什么?
5.在Python中,单引号、双引号或三引号中的文本片段代表“文字字符串”。尝试"abc" + "def"
和'abc' + 'def'
和'''abc''' + '''def'''
和"""abc""" + """def"""
。解释+运算符应用于字符串时的作用。✔
6.*
运算符可以应用于整数和字符串吗?尝试3 *'La'
并解释结果。
7.输入9−8*2+6
并解释结果。输入(5−1)*(1+2)**3
并解释结果。Python表达式中,“运算符的优先级”是什么(即首先应用哪些运算符)? ✔
8.■在Python提示符处输入17%3
,同时尝试15%4
和15%5
。%
运算符计算什么?与+
、 −
、*
、/和**
相比,运行一些测试以确定其等级(优先级)。 ✔
IDLE是一个简单的IDE(集成开发环境),用于编辑和运行Python代码。[2]
可以将简短的程序直接输入Shell:
>>> s = 0
>>> for k in range(1, 7):
s += k print(k, s)
1 1
2 3
3 6
4 10
5 15
6 21
>>>
但这并不是很实用,因为你必须重新输入每条语句,才能再次运行程序或对它进行小修改。在IDLE中,你可以复制以前的一个语句:将光标向上移动到相应的行,然后按<Enter>键。接着,你可以编辑该语句。
不过,重新输入每行代码太乏味了。将程序语句保存在文件中并从文件中执行程序,这样更实用。包含程序文本的文件称为源文件。Python源文件名的扩展名通常为.py。
你可以用任意的文本编辑器(如记事本)创建源文件。你甚至可以用文字处理程序,只需确保将文件另存为“纯文本”文件,并使用.py的替换文件名中的默认扩展名.txt。但是,编写简短Python程序最简单的方法是使用IDLE自带的内置编辑器。
在IDLE中打开新的编辑器窗口,请从File菜单中选择New File(或按<Ctrl+N>快捷键)。然后输入你的代码。如图1-6所示。
与纯文本编辑器(如记事本)不同,IDLE编辑器“了解”Python的某些特性。例如,它用不同颜色高亮显示了代码的不同元素。对于预期有缩进的语句,IDLE编辑器会自动增加“缩进”(向右移动):在for
、while
、if
、else
的冒号之后。按<BackSpace>键可以减少缩进级别。从File菜单中选择Save As...或按<Ctrl+Shift+S>快捷键,将程序保存到文件中。将.py扩展名与文件名一起使用,将文件保存在你选择的文件夹中。例如,C:\PythonProjects。
图1-6 使用IDLE编辑器输入代码
当IDLE编辑器窗口打开并处于活动状态时,你可以通过从Run菜单中选择Run Module或按F5键来测试程序。Python每次都会询问你是否要保存文件(单击Yes),你可以使用Options => Configure IDLE命令来禁用此功能。
如果程序有语法错误,Python会提醒你,并高亮显示第一个错误(发现分号而不是冒号)。如图1-7所示。
图1-7 Python显示语法错误
你可以同时打开多个文件,并在同一窗口中或在不同窗口间剪切和粘贴文本。选中并高亮显示要复制的文本,按<Ctrl+C>快捷键复制文本,将光标定位在插入点,然后按<Ctrl+V>快捷键粘贴文本。
1.编程语言“Python”的名称是指:
(A)希腊字符π
(B)英国喜剧团体
(C)基本亚原子粒子
(D)大蛇,如大蟒蛇
2.什么是源代码?
(A)包含该程序的页面的URL
(B)高级语言或汇编语言的程序文本
(C)编译成字节码的程序
(D)包含程序文本的文件的名称
3.当Python解释器遇到语法错误时会发生什么? ✔
(A)解释器继续并在结束时报告所有语法错误
(B)解释器尝试纠正错误并继续
(C)解释器报告错误并停止解释
(D)解释器Shell关闭
4.在IDLE中输入以下命令后会发生什么?
>>> import this
试试吧。
5.在IDLE中输入以下命令后会发生什么?
>>> import antigravity
试试吧。
6.如果你在没有打字或单击任何内容的情况下,让IDLE闲置很长时间,会发生什么?✔
(A)什么也没发生
(B)它保存所有打开的文件并关闭所有窗口
(C)它显示消息“I’ve been IDLE for too long!”
(D)它显示消息“For security reasons, your session has expired. Please log in to continue.
”
本章介绍的术语。
CPU
RAM
位
字节
KB
MB
GB
TB
PB
GHZ
编程语言
汇编语言
编译器
解释器
源代码
语法规则
bug
debug
冗余
解析
提示符
Shell
[1] 与流行的看法不同,Python并不是以蛇来命名,它是以英国喜剧团体Monty Python的名字命名的。他们的流行喜剧节目Monty Python’s Flying Circus于1969年至1974年在英国广播公司播出。IDLE是Python的集成开发环境,实际上暗示了该团体的成员Eric Idle。
[2] 有些人称Python为“脚本语言”,因为可以逐个交互地输入单条Python语句。这些人称Python程序为“脚本”。
在本章中,我们将介绍Python代码的一些元素,并介绍变量和算术运算符。
与其他编程语言一样,Python允许“注释”,即嵌入在程序中的短语或文本,它们可由人类阅读,但被解释器跳过。
与其他编程语言一样,Python使用一小组“关键字”(也称为“保留字”),这些关键字在Python程序中具有特定含义。
编程中“变量”的概念类似于代数中的变量,但它在编程中不那么抽象,更实用。
Python有7个算术运算符:普通的+
、−
、*
和/
,以及3个Python或编程特有的运算符。
在Python中,#
符号除了在引号内的情况外,表示“注释”(见图2-1)。注释的目的是使代码更具可读性。注释可以记录一段代码的作用,或解释模糊的代码。解释器并不关心注释,它只是跳过从#
到行尾的所有文本。
图2-1 注释
✦ ✦ ✦
图2-1中的def
和return
是Python的“关键字”,即在编程语言中具有特殊含义的字,不能用于命名程序员自己的变量或函数。def
表示我们正在定义一个函数,return
指定函数返回给调用者的值。(一旦定义了一个函数,你就可以从其他语句中调用它。我们将在第3章更详细地解释函数。)
注意“def”行末尾的冒号——它是语法规则所必需的。
Python 3.7有35个关键字,图2-2列出了其中的一些。
图2-2 一些Python关键字(保留字)
当你在IDLE中输入Python代码时,不同的语法元素将以不同的颜色显示。注释是红色的,关键字默认为橙色。
Python区分大小写,除了代表通用常量的3个保留字(None、True和False),所有保留字必须用小写字母书写。
✦ ✦ ✦
add_numbers
是我们给函数的名字,n
是我们给它的“参数”的名字(也称为“哑元”,即输入值)。
为变量和函数提供合理的、有意义的名称,这非常重要。
Python中的名称只能包含字母、数字和下划线字符,名称不能以数字开头。有效的名称如:total
、sum_3
、_a
、n2
。Python区分大小写,因此Total
与total
不同。在我们的示例中,我们可以调用函数sumFrom1ToN
,但更常见的Python风格是使用小写单词命名变量和函数,用下划线分隔,如add_numbers
或sum_digits
。
✦ ✦ ✦
def
行后面的行向右“缩进”。缩进行形成一个相关语句块,在本例中是函数的定义。缩进必须在块内保持一致,这是Python语法规则之一。习惯上将下一级别缩进4个空格。
一些编程语言使用花括号来描述语句块。Python不是这样。
在IDLE编辑器中按<Tab>键时,默认情况下会插入4个空格,但你可以在IDLE的首选项中更改缩进设置。
✦ ✦ ✦
除了注释之外,通常在def
行下面包含一个“Docstring”(文档字符串)(见图2-3)。这段文本通常放在三引号内(允许注释跨越多行),是可选的。这对于阅读代码的读者很有帮助,并且当你在IDLE的交互式Shell中输入该函数时,它将显示为“提示”。
图2-3 文档字符串
✦ ✦ ✦
在Python中,每个语句通常都写在单独的一行上。
一个例外是用三引号('''
或""")
括起来的字符串试试:
>>> msg = '''And it always goes on and on and on** and on and on'''
>>> msg
Python返回了msg
的值:
'And it always goes on\nand on and on\nand on and on'
消息中的\n
表示“换行”。当输出包含\n
的字符串时,\n
将下一个字符移动到下一行的开头。例如:
>>> print('And it always goes on\nand on and on\nand on and on')
And it always goes on
and on and on
and on and on
或:
>>> print('Line 1\nLine 2')
Line 1
Line 2
如果文档字符串超过一行,必须使用"""…"""或'''…''',但Python的格式手册建议始终使用三引号,即使对于单行文档字符串——为了保持一致性,使它更容易扩展。
如果一个语句太长而无法放在一行上,则可以在行尾添加\(反斜杠)并继续下一行。例如:
>>> 1 + 2 + 3 + 4 + 5 + 6 \
+ 7 + 8 + 9 + 10
55
但是,最好将该表达式放在括号中。
在多行上编写表达式的首选方式,是将它放在括号中。
例如:
>>> (1 + 2 + 3 + 4 + 5 + 6
+ 7 + 8 + 9 + 10)
55
Python允许你在一行上放置多个语句,尽管这不是常见的格式。为此,你必须使用分号分隔语句。例如:
>>> x = 3; y = 2; print(x + y)
5
1.在IDLE提示符处输入:
>>> from __future__ import braces
(“future”的两侧各有两个下划线)会显示什么?
2.以下函数返回字符串的第一个字符,或列表的第一个元素。
def first(s):
return s[0]
将文档字符串添加到此函数中,并在Python的提示符处输入以下代码:
def first(s):
< docstring >
return s[0]
现在尝试:
>>> first('Hello, world')
只要输入左括号,就会显示文档字符串作为“提示”。现在试试:
>>> first.__doc__
(Python在每一侧使用两个下划线来标记特殊的“系统”名称。)
3.以下哪些是Python关键字?✔
(A)while
(B)total
(C)none
(D)define
(E)continue
(F)IF
4.在第1章图1-3展示的函数中,识别4个关键字。✔
5.在以下函数定义语句中,识别两个语法错误:
def bad_Code(x)
Return x**2 - 1
6.以下语句的输出是什么?✔
print('One is better than \none' +\
'; two is better than one')
7.以下语句的输出是什么?
print('Python is #1')
8.尝试输出以下字符串:
print('What's up')
print("What's up")
print("She said "What's up"")
print("She said \"What\'s up\"")
字符串(引号内的文字)中的\"和\'表示什么?
9.在以下代码中查找语法错误。
def mystery(n):
"""Return n cubed."""
return n**3
✔
在编程理论中,变量是一个“命名的容器”,可以将之理解为一个附加了名称标签的内存位置。在不同时间可以将不同的值存储在变量中。你可以检查存储在变量中的值,并将新值放入其中。[1]
例1
>>> x = 3
>>> x
3
>>> x = 5
>>> x
5
>>> x = 2*x - 1
>>> x
9
请注意,x = 2*x −1
不是等式,不像在数学中那样,而是一组指令:
取x
的当前值;
乘以2
;
减去1
;
将结果存回x
中。
在Python中,每个值都是一个“对象”。Python支持几种内置类型的对象:整数和实数、字符串、列表等。(程序员也可以定义自己的对象类型,并在程序中创建它们的实例。)Python有一个名为type
的内置函数,它接收任意对象并返回它的类型。
例2
>>> x = 3
>>> type(x)
<class 'int'>
>>> x = 1.5
>>> type(x)
<class 'float'>
>>> x = 'Hello'
>>> type(x)
<class 'str'>
>>> x = '*'
>>> type(x)
<class 'str'>
我们从这些例子中学到了什么?
1.若要引入一个新变量,我们要做的就是给它命名,并使用=为它赋值。
2.如果我们在提示符处输入变量的名称,Python将显示它的当前值。
3.Python有几种内置的对象类型。
int
类型的对象包含整数值。float
类型的对象包含实数(或其近似值)。实数的类型称为float
,因为这些数字作为浮点数存储在计算机中。这将在第6章中讨论。str
类型的对象包含一串字符(或单个字符)。4.同一个变量可以在不同的时间保存不同类型的对象。
5.在Python中,每个对象“都知道”它自己的类型。我们不必明确告诉变量存储在其中的对象类型。
✦ ✦ ✦
变量名由程序员选择。
变量的名称只能包含字母、数字和下划线字符,并且不能以数字开头。Python要求所有变量名称以小写字母或下划线开头。
变量可以用在“表达式”中。
例3
>>> tax_rate = 0.05
>>> price = 48.00
>>> total = price * (1 + tax_rate)
>>> total
50.400000000000006
以下语句是如何工作的?
total = price * (1 + tax_rate)
首先,Python确保定义了变量price
和tax_rate
,然后获取它们的值,并将它们插入表达式price * (1 + tax_rate)
。如果其中一个值与使用它的操作不兼容,Python会“引发异常”(报告错误)。如果一切正常,Python会计算结果,并将它放入变量total
中。
▼
请注意,结果并不准确。误差是由于实数在计算机中近似地表示为二进制浮点数,可能存在小差异。有一种方法可以获得更简洁的输出:
>>> print('Total sale: {0:6.2f}'.format(total))
Total sale: 50.40
{0:6.2f}
是格式字符串中的占位符,它在宽度为6的字段中对float值进行右对齐,小数点后面有两位数;0:
告诉Python将第一个参数(total
)插入占位符,并适当地对它进行舍入处理。
▲
计算表达式并将它赋值给变量后,即使更改了表达式中使用的变量值,其值也不会自行更改。
例4
# continued from Example 3
...
>>> price = 60.00
>>> total
50.400000000000006
要看到price的最终值,你需要明确地重新计算该表达式:
>>> total = price * (1 + tax_rate)
>>> total
63.0
✦ ✦ ✦
“变量”可以保存一个“常量”,即在程序运行期间不会改变的值。例如:
pi = 3.1415926535897932
(这个常量在Python模块math
中定义。你将在第3.6节中学习如何将它“导入”Python程序。)
习惯上,重要的通用常量的名称全用大写。例如:
KM_IN_MILE = 1.60934
✦ ✦ ✦
▼
说实话,我们没有告诉你关于变量的全部真相。事实上,Python变量不包含对象——它们包含对象的“引用”。引用基本上是对象在内存中的地址。某些对象(如长字符串或列表)会占用大量存储空间,将它们的值从一个变量复制到另一个变量会太慢。作为替代,当我们赋值b = a
时,我们只将引用(即地址)从a
复制到b
中。两者都指向同一个对象(见图2-4)。
图2-4 Python变量保存对象的引用
只要对象是“不可变的(immutable)”,即永远不会改变,这不会引起任何混淆。所有数字和字符串都是不可变对象,一旦被创建,它们就无法更改。但是,列表并非一成不变。试试这个:
>>> a = [1, 2] # list [1, 2] is assigned to variable a
>>> b = a >>> b
...
>>> a.append(3)
>>> b
...
你必须小心!
▲
1.定义变量r = 5
。为定义一个常量,精确到5位小数。定义一个名为area
的变量,并将它设置为半径为r
的圆的面积。✔
2.解释结果:
>>> x = 5
>>> x = 2*x
>>> print(x)
3.■在Python中,以下哪些是语法有效的变量名称?
name,d7,2x,first_name,lastName,Amt,half-price,'Bob',LBS_IN_KG
哪些变量名称的形式好? ✔
4.定义变量first_name
,等于你的名字。定义变量last_name
,等于你的姓氏。写一个表达式连接(链接在一起)first_name
和last_name
,中间有一个空格,并将该表达式赋值给一个新变量。
5.填空:
>>> x = 1.0
>>> x = x + 3
>>> type(x)
6.■以下代码的输出是什么?
a = 3
b = 2
a = a + b
b = a - b
print(a)
print(b)
✔
7.■在Python中,
name = input('What is your name? ')
显示“What is your name?
”提示符,然后将name
设置为用户输入的字符串。编写一个函数,询问用户姓名,并显示“Hello,
<用户输入的名称>. Welcome to Python!
”。为你的函数提供合理的名称,并提供文档字符串。 ✔
如你所见,算术运算符+
、−
、*
和/
,用于加法、减法、乘法和除法,与算术和代数几乎相同。
与数学不同的是,乘法符号不能省略。
如果没有括号,先执行乘法和除法,然后执行加法和减法。可以像数学中那样使用括号,用于改变操作的顺序。
除了4个标准算术运算符+
、−
、*
、/
,Python还有3个算术运算符。
n%m
(读作“n
模m
”)计算n除以m时的余数。例如,17%3
得到2
,而4%10
得到4
。//
运算符称为“整数除法”运算符,通常适用于整数操作数。n//m
的结果是一个最接近其比值的整数,等于或低于其比值。例如,8//3
得到2
,而5//9
得到0
。x**n
表示x的n次幂。例如,2**3
得到8
。%
和//
具有与*
和/
相同的优先级(等级);**
具有更高的优先级,会首先计算。
▼
Python还有一个内置函数divmod
,当n除以m时,使用它计算商和余数,如q, r = divmod(n, m)
将q
设置为n // m
,r
设置为n%m
。例如:
cents = 144
print(cents, 'cents =', end=' ')
quarters, cents = divmod(cents, 25)
dimes, cents = divmod(cents, 10)
nickels, cents = divmod(cents, 5)
print(quarters, 'quarters +', dimes, 'dimes +',
nickels, 'nickels +', cents, 'cents')
输出:
144 cents = 5 quarters + 1 dimes + 1 nickels + 4 cents
▲
✦ ✦ ✦
在前面的例子中,你可能已经注意到了s += k
这样的语句。+=
是“增强(或复合)”赋值语句中使用的符号之一:+=
,−=
,*=
,/=
,%=
,//=
,**=
。
x += 3
与x = x + 3
相同,意味着将x加3。
其他增强赋值以类似的方式工作。你可以将增强赋值与任何“二元运算符(即使用两个操作数的运算符)”一起使用。经验丰富的程序员写出x = x + 1
而不是x += 1
这样的语句,会被认为“不酷”。
+=
也适用于两个字符串或列表,*=
也适用于整数和字符串或列表。
1.在不更改表达式值的情况下尽可能多地删除括号,并在Python Shell中验证结果。
(((3 + 7)//2)%2)**3
2.从以下Python表达式中删除所有多余的括号。
(x - 2)**3 + (3*x) ✔
3.以下语句执行后x
的值是多少?
x = 5
x += 3
x *= 5
4.填空。
>>> x = 5
>>> x //= 2
>>> x//2%2/2
5.■编写两个语句计算x4,不使用**
运算符,只进行两次乘法运算。✔
6.■以下代码的输出是什么?
n = 5
s = '+' * n
print(s)
7.(a)写一个函数triangle(s)
,输出一个由s
组成的倒三角形,其中s
是一个字符的字符串。例如,triangle('*')
应输出:
*****
***
*
使用3个print
语句,且不用其他语句。
(b)■你的函数不应该有return
。不过,你的函数还是会返回某些东西。它是什么,你怎么知道的?✔
(c)■写另一个版本的triangle(s)
,只使用一条print
语句。
(d)◆修改(a)中的triangle(s)
,使得如果s
是较长的字符串,你的函数仍显示由s
组成的对称三角形。例如,如果s
为'La'
,则显示的三角形应为:
LaLaLaLaLa
LaLaLa
La
»提示:len(s)
返回s
中的字符数。例如,len('La')
返回2。;
本章介绍的术语。
注释
缩进
关键字(保留字)
变量
常量
算术运算符
操作符的优先级
增强算术语句
对象
本章介绍的一些Python特性。
#
标记注释,延伸到行尾
文档字符串
用def
定义一个函数并用return
返回其结果
一个相关的语句块是缩进的
字符串:'abc'
,"abc"
,'''abc'''
或"""abc"""
\ n
是换行符
\
在行的末尾意味着继续下一行
+
、−
、*
、/
、%
、//
、**
运算符
用+=
、−=
、*=
、/=
、%=
、//=
、**=
进行增强(复合)赋值
内置函数type
[1] 许多“Python爱好者(Pythonistas)”更喜欢将变量名称视为贴在值上的即时贴。