计算机科学丛书
点击查看第二章
点击查看第三章
Python 程序设计与问题求解(原书第2版)
Fundamentals of Python:First Programs,Second Edition
[美] 肯尼斯· A. 兰伯特(Kenneth A. Lambert ) 著刘鸣涛 孙 黎 甘 靖 译
第1章
引言
完成本章的学习之后,你将能够做到以下几点:
● 描述算法的基本特征。
● 解释在计算机体系结构中硬件和软件是如何协作的。
● 总结计算机的发展简史。
●编写并运行一个简单的Python 程序。
作为本书的读者,你一定至少玩过一款电子游戏,并且听过数字音乐。很有可能的是,用微波炉里准备了零食后,你已经看完一部数字电影了。一天之中,你会拨打电话、发送或接收短信、拍照或在手机上浏览并查询你最喜爱的社交网络。你和你的朋友会使用台式电脑或笔记本电脑完成一些高中或大学里比较重要的课程。
以上提及的这些活动都依赖于一个共同点:计算机技术。计算机技术几乎无处不在,不仅在家中,在学校和我们工作、休闲的地方也存在。计算机技术在娱乐、教育、医疗、制造、通信、政府和商业等诸多领域中均扮演着重要的角色。有人说,我们拥有数字生活方式,我们生活在一个以信息为基础的经济信息时代。而有的人甚至声称,自然本身就是对DNA 中存在的信息结构和亚原子粒子之间的关系进行计算的。
尽管我们没有具体设想实际的计算机是什么样子,但不难想象如果世界没有了计算机将是什么样子。同样不可思议的是,人类几千年来都没有使用计算机技术,而仅仅在最近的三十几年,计算机技术已经遍及我们所了解的整个世界。
在下面的章节中,你将学习计算机科学,这是对令这项新技术和这个新世界成为可能的计算方法的研究。你还将学习如何有效和适当地利用计算机来改善自己和他人的生活。
1.1 计算机科学的两种基本思想:算法和信息处理
跟大多数的研究领域一样,计算机科学涉及一系列广泛的相互关联的思想。其中最基本的两个思想是算法和信息处理。本节会对这两个基本思想做简要介绍,后面的章节中会详细地介绍它们。
1.1.1 算法
在当代的计算设备发明之前,人们早就已经开始进行计算了,而且许多人依然在使用现在看来比较“原始”的计算设备。例如,考虑一下在信用卡、袖珍计算器或收银机出现之前,商家是如何为市场上的顾客找零钱的。找零钱是一项复杂的活动,这可能需要你花费一些时间来学习如何去做,并且每一次都需要集中精力去做。让我们考虑一下这个过程中都涉及什么。
一种方法是,计算出购买价格和顾客给商家的货币金额之间的差额。这个计算的结果就是商家必须返回给顾客的总金额。例如,如果你以2.39 美元的价格从农民手里购买了一打鸡蛋,并且给农民一张10 美元的钞票,那么她应该向你返还7.61 美元。因此,她要选择适当的硬币和钞票凑成7.61 美元,这些累加上2.39 美元时,正好10 美元。
另一种方法是,商家从购买价格开始逐步追加到给定的金额。首先,选择硬币将金额凑成整数美元(在本例中,购买价格2.39 美元,首先需要0.61 美元来凑3 美元,所以需要3 美分、1 镍和4 便士的硬币),然后选择适量的美元将金额凑成5 美元(在本例中,需要2 美元),接下来还需要5 美元凑成10 美元来完成交易。正如你在本书中将会看到的那样,有很多可能的方法或算法可用于解决同样的问题,而如何从中选出最好的一个将是你通过练习获得的技能。
很少有人可以在不借助手工辅助工具(如铅笔和纸)的情况下做三位数字减法。正如你在小学里学到的,可以按照一系列明确的步骤用铅笔和纸做减法。这样的运算你可能已经做过多次了,不过不会想到列出所涉及的具体步骤。编制这样的列表来解决问题是计算机科学家一直在做的事情。例如,以下步骤描述了使用铅笔和纸张计算两个数字相减的过程:
步骤1:写下这两个数字,其中较大数字在较小数字之上,并且数字右对齐排列。
步骤2:假设你将从最右边的一列数字开始,从右向左每一列依次计算。
步骤3:写下当前数字列中的两位数字之间的差,如有需要,跟左边一列上的数字借1。
步骤4:直到最左边一列算完,停止。否则,移动到左侧的下一列,然后返回到步骤3。
如果计算智能体(在这里是指人)能按照这些简单的步骤正确地执行,则整个过程结束后就会得到给定问题的正确解决方案。假设在步骤3 中,智能体已经知道如何计算任何给定列中的两个数字之间的差,以及可能需要的借位操作。
在找零钱的过程中,大多数人可以找出代表正确找零数的硬币和纸币的组合,而不需要任何人工辅助。但是,涉及的心算仍然可以用前面的分步骤方式描述,如果对找零的正确性存在争议,可以把步骤写在纸上。
每一组描述像这样的计算过程的步骤序列称为一个算法。打个比方,算法就像一个配方。它提供了一套指令,告诉我们如何做某些事情,比如找零钱、烤面包或者组装一件家具。更确切地说,算法描述了一个以解决问题为导向的过程。算法也是计算机科学的基本思想之一。算法具有以下特征:
● 算法由有限数量的指令组成。
●算法中每条单独的指令都有明确的定义。这意味着指令所描述的动作能被有效实施或者被计算智能体执行。例如,任何具备算术能力的计算智能体都可以计算两个数字之间的差。所以,“计算两个数之差”的算法步骤可被明确定义。而“用0 除以一个数”这样的步骤没有明确的定义,因为没有计算智能体可以执行。
● 算法描述一个过程,这个过程在得到问题的解决方案之后停止。例如,在计算智能体写下最左列中的两个数字之差后,减法过程停止。
●算法解决一类问题。例如,描述如何找零的算法应该适用于差额大于或等于0 美元的任意两笔金额。
创建一个描述如何找零的步骤序列对你来说应该算不上什么主要成就,但是将一项任务分解成多个组成部分是计算机程序员的主要工作之一。一旦编写算法来描述特定类型的计算,就可以构建一台计算机来执行计算。换句话说,如果我们能够开发一种算法来解决问题,就可以自动完成解决问题的任务。有时没有必要写一个计算机程序来自动完成变更任务,因为你已经可以很容易地做出改变了。但是,假设你需要完成一件更复杂的任务,例如排序100 个名字的列表,在这种情况下,电脑程序将非常方便。
计算机可以运行一小组算法来执行专门的任务,例如操作微波炉。但是我们也可以构建另一种计算机,就像放在你桌面上的电脑一样,它们能够执行任何算法描述的任务。这些电脑是真正的通用问题解决机器。它们不像我们以前构建过的任何机器,它们构成了我们生活的全新世界的基础。
在本书后面的部分,我们将介绍用于表达算法的符号和一些设计算法的建议。你会发现算法和算法思想是任何计算机系统的关键基础。
1.1.2 信息处理
自从几千年前人类首先学会写作以来,他们就已经在处理信息。信息本身在历史中采取过许多形式,从古代美索不达米亚的泥土上的印记,到古希腊的第一个书面文本,到欧洲文艺复兴以来大量生产的书籍、报刊和杂志上的印刷文字,到过去350 年中使用的现代数学和科学的抽象符号。然而,直到最近,人们才开发出通过构建计算机来自动处理信息的能力。在现代计算机世界中,信息通常也被称为数据。但是,什么是信息?
像数学计算一样,信息处理可以用算法来描述。在我们之前做出改变的例子中,减法步骤涉及操纵用于表示数字和金钱的符号。在执行任何算法的指令时,计算智能体处理信息。计算智能体从一些给定的信息(称为输入)开始,根据定义好的规则来转换这些信息,并产生新的信息,即输出。
认识到描述信息处理的算法也可以表示为信息是很重要的。计算机科学家已经能够以一种可被机器有效执行的形式表示算法。他们还设计了真正的机器,称为电子数字计算机,它们能够执行算法。
最近,计算机科学家发现了如何将诸如图像、音乐、人类言语和视频等许多其他事物表示为信息。如果没有这种新的信息处理,我们现在熟知的许多媒体和通信设备将是不可能的。后面的章节中会详细地介绍这些成果。
■.练习
这些简短的节末练习旨在激发你对计算的思考。
- 列出三种常见类型的计算智能体。
- 编写一个算法来描述更改过程的第二部分(计算出硬币和账单)。
- 编写描述一个常见任务的算法,例如烘焙蛋糕或操作DVD 播放器。
- 描述一个没有明确定义的指令,因此不能作为算法中的一个步骤。举一个这样的指令的例子。
- 为什么说笔记本电脑是一种通用的问题解决机器?
- 列出使用计算机的四台设备并描述它们处理的信息。(提示:考虑设备的输入和输出。)
1.2 现代计算机系统的结构
现在简单介绍一下现代计算机系统的结构。现代计算机系统由硬件和软件组成。硬件由执行算法所需的物理设备组成。软件是这些算法的集合,表示为程序,特别是编程语言。在接下来的讨论中,我们将重点讨论典型台式计算机系统中的硬件和软件,尽管在其他计算机系统中也可以找到类似的组件,例如手持设备和ATM (自动取款机)。
1.2.1 计算机硬件
计算机的基本硬件组件是存储器、中央处理器(CPU)和一组输入/ 输出设备,如图1-1 所示。
人类用户主要与输入和输出设备交互。输入设备包括键盘、鼠标、触控板、麦克风和触摸屏。常见的输出设备包括显示器和扬声器。计算机还可以通过各种端口与外部世界通信,这些端口将计算机连接到网络以及智能手机和数码相机等其他设备。大多数输入设备的目的是将人类处理的信息(如文本、图像和声音)转换为用于计算处理的信息。大多数输出设备的目的是将处理的结果转换回人类可用的形式。
建立计算机存储器的目的是以电子形式表示和存储信息。具体而言,信息存储为二进制数字(1 和0)的模式。要了解这是如何工作的,请考虑一个基本设备,如电灯开关,它只能处于两种状态之一,开或关。现在假设有一排开关控制着16 盏小灯。通过关闭或打开开关,可以将16 位二进制数字的任何模式表示为打开或关闭小灯的模式。我们将在本书后面看到,计算机科学家已经发现如何以二进制形式表示任何信息,包括文本、图像和声音。
现在,假设有8 排灯,每排16 个。我们可以选择任意一排灯,检查或更改该集合中每个灯的状态。我们刚刚开发了一种微型计算机存储器。存储器有8 个单元,每个单元可以存储16 位二进制信息。图1-2 显示了该模型的示意图,其中存储单元填充有二进制数字。这种存储器有时也称为主存储器、内部存储器或随机存取存储器(RAM)。
存储在存储器中的信息可以表示任何类型的数据,例如数字、文本、图像或声音,或者程序的指令。我们还可以在内存中存储一个编码为计算机二进制指令的算法。一旦信息被存储在内存中,我们通常想用它做点什么,也就是说,我们想处理它。负责处理数据的计算机部分是中央处理器(CPU)。这种设备有时也称为处理器,由电子开关组成,用来执行简单的逻辑、算术和控制操作。CPU 通过从存储器中提取二进制指令、解码并执行它们来执行算法。执行指令可能还需要从内存中获取其他二进制信息(数据)。
处理器可以非常快速地定位计算机主存储器中的数据。然而,这些数据只有在电力进入计算机时才存在。如果电源故障或关闭,主存储器中的数据将丢失。显然,需要更永久性的内存来保存数据。这种更持久的内存称为外部或辅助内存,它有几种形式。磁带和硬盘等磁存储介质允许位模式作为模式存储在磁场中。半导体存储介质(例如闪存棒)与光学存储介质(例如CD 和DVD)以不同的技术实现几乎相同的功能。这些辅助存储介质中的一些可以容纳比计算机的内部存储器大得多的信息量。
1.2.2 计算机软件
你已经知道计算机是一种通用的解决问题的机器。要解决任何可计算的问题,计算机必须能够执行任何算法。因为不可能预见存在算法解决方案的所有问题,所以无法将所有潜在的算法“硬连线”到计算机硬件中。相反,我们在硬件处理器中构建一些基本操作,并需要任何算法来使用它们。这些算法被转换成二进制形式,然后与它们的数据一起加载到计算机的存储器中。之后处理器可以通过运行硬件的更基本的操作来执行算法的指令。
存储在内存中以便以后执行的任何程序都称为软件。存储在计算机内存中的程序必须用二进制数字表示,也称为机器代码。对人类来说,一次将机器代码加载到计算机内存中一个数字将是一项乏味且容易出错的任务。如果能自动完成这个过程,每次都能把它做好,那将会很方便。为此,计算机科学家开发了另一个程序,叫作加载器,来执行这项任务。加载器将一组机器语言指令作为输入,并将它们加载到适当的存储位置。加载程序完成后,机器语言程序就可以执行了。显然,加载程序无法将自身加载到内存中,因此这是必须硬连线到计算机的算法之一。
现在有了加载程序,我们就可以加载和执行其他程序,这些程序使程序的开发、执行和管理变得更加容易。这种类型的软件称为系统软件。系统软件最重要的例子是计算机的操作系统。你可能已经熟悉了至少一个最流行的操作系统,比如Linux、苹果的macOS 和微软的Windows 。操作系统负责管理和调度多个并发运行的程序。它还管理计算机的存储器,包括外部存储器,并管理CPU、输入/ 输出设备和网络上其他计算机之间的通信。任何操作系统的一个重要部分是文件系统,它允许人类用户将数据和程序组织在永久存储器中。操作系统的另一个重要功能是提供用户界面,即人类用户与计算机软件交互的方式。基于终端的界面接受键盘输入,并在显示器屏幕上显示文本输出。图形用户界面(GUI)围绕桌面隐喻来组织显示器屏幕,在Windows 中,这些隐喻包含文件夹、文件和应用程序的图标。这种类型的用户界面还允许用户使用诸如鼠标的定点设备来操纵图像。触摸屏界面支持用手势(例如用户手指的捏和刷)更直接地操纵这些视觉元素。以口头和其他方式对口头命令做出反应的设备也变得越来越普遍。
另一种主要类型的软件叫作应用软件,或简称应用(APP)。应用程序是为特定任务设计的程序,例如编辑文档或显示网页。应用程序包括Web 浏览器、文字处理器、电子表格、数据库管理器、图形设计包、音乐制作系统和游戏,以及数百万个其他应用程序。当你开始学习写计算机程序时,你将首先集中精力写简单的应用程序。
你已经了解到,计算机硬件只能执行以二进制形式(即机器语言)编写的指令。然而,编写机器语言程序将是一项非常乏味、容易出错的任务。为了简化编写计算机程序的过程,计算机科学家开发了高级编程语言来表达算法。这些语言类似英语,程序员可以用别人能理解的形式表达算法。
程序员通常从在文本编辑器中编写高级语言语句开始。然后,程序员运行另一个称为翻译器的程序,将高级程序代码转换为可执行代码。因为程序员甚至在编写高级代码时也可能犯语法错误,所以翻译器在完成翻译过程之前会检查语法错误。如果检测到这类错误,翻译器通过错误消息警告程序员。然后程序员必须修改程序。如果翻译过程成功而没有语法错误,程序可以由运行时系统执行。运行时系统可以直接在硬件上执行程序,或者运行另一个称为解释器或虚拟机的程序来执行程序。图1-3 显示了编码过程中使用的步骤和软件。
■.练习
- 列举两个输入设备和两个输出设备。
- 中央处理器(CPU)做什么?
- 硬件存储器中的信息如何表示?
- 基于终端的界面和图形用户界面有什么区别?
- 翻译器在编程过程中扮演什么角色?
1.3 计算系统简史
现在我们已经了解了计算和计算机系统的一些基本概念,接下来花点时间来研究它们在历史上是如何形成的。图1-4 总结了计算历史上的一些主要发展,下面的讨论提供了关于这些发展的更多细节。
1.3.1 在电子数字计算机之前
古代数学家开发了第一批算法。“算法”这个词来自一位波斯数学家穆罕默德·伊本·穆萨·阿尔·赫瓦里兹米的名字,他在9 世纪时写了几本数学教科书。大约2300 年前,几何的发明者、希腊数学家欧几里得开发了一种计算两个数字最大公约数的算法。
古代也出现了一种叫作算盘的装置。算盘帮助人们执行简单的算术。用户通过在木棍网格上滑动珠子来计算总和和差异(见图1-5a)。算盘上的珠子构成了数据。
17 世纪,法国数学家布莱斯·帕斯卡(1623—1662 年)建造了第一批使加法过程自动化的机械设备之一(见图1-5b)。加法操作嵌入机器内的齿轮配置中。用户通过旋转一些轮子输入两个要相加的数字,总和或输出数出现在另一个旋转轮上。德国数学家戈特弗里德威廉·莱布尼茨(1646—1716 年)建造了另一台机械计算器,包括其他算术功能,如乘法。莱布尼茨和牛顿一起发明了微积分,他接着提出了用符号计算的想法,这是我们最基本和最普遍的智力活动之一。他主张使用一种通用语言,通过计算可以解决任何问题。
19 世纪早期,法国工程师约瑟夫·玛丽·雅卡尔(1752—1834 年)设计并制造了一台自动编织过程的机器(见图1-5c)。在此之前,编织图案中的每一行都必须手工设置,这是一个非常烦琐、容易出错的过程。这台织机被设计成接受一组穿孔卡片形式的输入,每张卡片都描述了一排布料图案。尽管它仍然是一个完全机械的装置,但却拥有以前的装置所缺乏的东西——自动执行算法的能力。这组卡片表达了控制织机行为的算法或指令集。如果织机操作员想要生产不同的图案,他只需要用不同的一套卡片来运行机器。
英国数学家查尔斯·巴贝奇(1792—1871 年)将可编程计算机的概念向前推进了一步,他设计了一种机器模型,从概念上来说,它与现代通用计算机非常相似。巴贝奇将他的机器——他称之为分析引擎——视为一种机械装置。他的设计需要四个功能组件:一个执行算术运算的工厂,一个保存数据和程序的商店,一个运行穿孔卡片指令的操作员,以及一个在穿孔卡片上产生结果的输出。可悲的是,巴贝奇的电脑从未被制造出来。巴贝奇本人去世时,这个项目因缺乏资金而夭折。
在19 世纪的最后二十年里,一位名叫赫尔曼·霍尔瑞斯(1860—1929 年)的美国人口普查局统计员开发了一种自动处理美国人口普查数据的机器。霍尔瑞斯的机器具有与巴贝奇的分析引擎相同的部件,它只接受一组穿孔卡片作为输入,然后对卡片进行计数和分类。他的机器大大缩短了产生美国人口统计结果的时间。寻求自动化数据处理的政府和商业组织很快采用了霍尔瑞斯的穿孔卡片机。霍尔瑞斯也是一家最终成为IBM(国际商业机器)的公司的创始人之一。
同样在19 世纪,英国中学教师乔治·布尔(1815—1864 年)发展了一套逻辑系统。这个系统包括一对值——真值和假值,以及对这些值的三个原始操作——与、或、非。布尔逻辑最终成为设计处理二进制信息的电子电路的基础。
半个世纪后的20 世纪30 年代,英国数学家艾伦·图灵(1912—1954 年)探索了算法和计算的理论基础和局限性。图灵的主要贡献是发展了一种通用机器的概念,它可以专门用来解决任何可计算的问题,并证明了一些问题是计算机无法解决的。
1.3.2 第一台电子数字计算机(1940 ~1950)
20 世纪30 年代末,麻省理工学院的数学家和电气工程师克劳德·香农(1916—2001 年)写了一篇题为“继电器和开关电路的符号分析”的经典论文。在这篇论文中,他展示了其他系统中的操作和信息(如算术)如何被简化为布尔逻辑,然后被简化为硬件。例如,如果布尔值TRUE 和FALSE 被写为二进制数字1 和0,则可以编写一个逻辑操作序列,计算两个二进制数字字符串的和。构建电子数字计算机所需要的只是将二进制数字表示为开/ 关的电子开关以及表示其他电路中的逻辑运算的能力。
二战中战斗人员的需求推动了计算机硬件的发展。美国、英国和德国的几个科学家和工程师团队在20 世纪40 年代独立创造了第一代通用数字电子计算机。所有这些科学家和工程师都利用香农的创新,用电子开关设备来表达二进制数字和逻辑运算。这些团体中有一个在霍华德·艾肯指导下的哈佛大学团队。他们的计算机名为Mark I ,于1944 年开始运行,在战争期间为美国海军做数学工作。Mark I 被认为是电动机械设备,因为它使用磁铁、继电器和齿轮的组合来存储和处理数据。
宾夕法尼亚大学的普雷斯佩尔·埃克特和约翰·毛克利领导的另一个团队生产了一台名为ENIAC(电子数字积分器和计算器)的计算机。ENIAC 计算了战争结束时美国陆军炮兵的弹道表。ENIAC 完全使用电子元件,它比Mark I 快了近一千倍。
另外两台电子数字计算机比ENIAC 稍早完成。它们是1942 年由爱荷华州立大学的约翰·阿坦索夫和克利福德·贝里建造的ABC(阿坦索夫-贝里计算机),以及1943 年由艾伦·图灵手下一个在英格兰工作的团队建造的Colossus。创建ABC 是为了求解联立线性方程组。尽管ABC 的功能比ENIAC 的功能要窄得多,但ABC 现在被视为第一台电子数字计算机。直到最近,Colossus 的存在一直是绝密的,在战争期间,它被用来破解强大的德国Enigma 密码。
第一代电子数字计算机,有时称为大型计算机,由真空管、电线和插头组成,充满了整个房间。虽然它们比人类在计算方面要快得多,但按照我们目前的标准,它们的速度非常慢,而且容易崩溃。此外,早期的计算机极难编程。为了进入或修改程序,一组工人必须通过拔掉和重新接上电线来重新排列真空管之间的连接。每个程序都是通过硬连线到计算机上来加载的。有成千上万的电线,很容易出错。
第一批计算机的存储器只存储数据,而不是处理数据的程序。正如我们已经看到的,存储程序的想法最早出现在100 年前雅卡尔的织机和巴贝奇的分析引擎设计中。1946 年,约翰·冯·诺依曼意识到程序指令也可以二进制形式存储在电子数字计算机的存储器中。他在普林斯顿的研究小组开发了首批现代存储程序计算机之一。
尽管计算机的尺寸、速度和应用自早期以来已经发生了巨大的变化,但是电子数字计算机的基本结构和设计仍然非常稳定。
1.3.3 第一种编程语言(1950 ~1965)
今天的计算机用户运行着许多程序,由数百万行代码组成,执行三四十年前看似神奇的任务。但是第一台数字电子计算机没有我们今天认为的软件。一些相对简单和小型的应用程序的机器代码必须手工加载。随着对更大和更复杂应用程序的需求的增长,对加速编程过程的工具的需求也在增长。
在20 世纪50 年代早期,计算机科学家意识到可以用符号代替机器代码,第一种汇编语言出现了。程序员会在键控打孔机上输入操作的助记码,如ADD 和OUTPUT,以及数据变量,如工资和费率。按键为每条指令在一张小卡片上打一组孔。程序员随后将一叠叠卡片交给系统操作员,系统操作员将它们放在一个叫作读卡器的设备中。这种设备将卡片上的孔转换成计算机内存中的模式。然后,汇编器将内存中的应用程序翻译成机器代码并执行。
汇编语言编程是对机器代码编程的有效改进。汇编语言中使用的符号对人们来说更容易阅读和理解。另一个优点是,汇编程序可以在程序实际执行之前捕获一些编程错误。然而,与传统数学符号相比,汇编符号仍然显得有点晦涩难懂。为了解决这个问题,IBM 的程序员约翰·巴克斯于1954 年开发了FORTRAN (公式翻译语言)。程序员,其中许多是数学家、科学家和工程师,现在可以使用传统的代数符号。FORTRAN 程序员仍然在打孔机上输入程序,但是计算机在程序被编译器翻译成机器代码后执行了这些程序。
FORTRAN 被认为是数值和科学应用的理想选择。然而,表达数据处理中使用的数据类型——特别是文本信息——是很困难的。例如,FORTRAN 在处理包括人名、地址、社会保险号码以及公司和其他机构的财务数据在内的信息时并不实用。20 世纪60 年代早期,由格蕾丝·霍珀少将率领的团队开发了COBOL(通用面向业务的语言),用于美国政府的数据处理。银行、保险公司和其他机构很快在数据处理应用中采用了它。
同样在20 世纪50 年代末和60 年代初,麻省理工学院的计算机科学家约翰·麦卡锡开发了一种强大而优雅的表示计算的符号LISP(列表处理)。基于递归函数的理论(第6 章中涉及的主题),LISP 抓住了符号信息处理的本质。麦卡锡的学生史蒂夫·塞卢斯在1960 年为LISP 编写了第一个解释器。解释器直接接受LISP 表达式作为输入,评估并打印结果。早期,LISP 主要用于实验室,他们的研究领域被称为人工智能。最近,LISP 被吹捧为解决任何困难或复杂问题的理想语言。
尽管FORTRAN 和LISP 是第一批高级编程语言,但它们已经存活了几十年。它们都经历了许多修改来提高能力,并且已经成为许多其他编程语言开发的模型。相比之下,COBOL 不再被积极使用,而是主要以遗留程序的形式存活下来,这些程序仍然需要维护。
这些新的高级编程语言有一个共同的特点:抽象。在科学或任何其他研究领域,抽象允许人类将复杂的想法或实体简化为更简单的想法或实体。例如,在FORTRAN 中,一组10 个汇编语言指令可能会被一个仅由5 个符号组成的等效代数表达式代替。换句话说,用更少的资源说更多的话,就是在使用抽象。在计算的其他领域,例如硬件设计和信息架构,也可以找到抽象的使用。复杂性实际上并没有消失,但是抽象隐藏了它们。通过抽象抑制分散注意力的复杂性,计算机科学家可以概念化、设计和构建更加复杂的系统。
1.3.4 集成电路、交互和分时(1965 ~1975)
20 世纪50 年代末,真空管被晶体管取代,成为在计算机硬件中实现电子开关的机制。作为固态器件,晶体管比真空管小得多,更可靠,更耐用,制造成本也更低。因此,计算机的硬件组件通常在物理尺寸上变得更小、更可靠和更便宜。电子开关越小越多,处理速度越快,存储信息的内存容量也越大。
20 世纪60 年代早期,集成电路的发展使得计算机工程师能够制造更小、更快、更便宜的计算机硬件组件。他们完善了在非常薄的硅晶片上蚀刻晶体管和其他固态元件的照相工艺,将整个处理器和存储器留在单个芯片上。1965 年,计算机芯片制造商英特尔的创始人之一戈登·摩尔做出了一个称为摩尔定律的预测。该预测指出,硬件的处理速度和存储容量将会增加,其成本将每18 个月降低至约为原来的1/2。这一趋势已经持续了50 多年。例如,在1965 年,一个芯片上大约有50 个电子元件,而到2000 年,一个芯片可以容纳4000 多万个元件。没有集成电路,人类就不会在1969 年登月,也不会有我们现在日常使用的功能强大、价格低廉的手持设备。
20 世纪60 年代出现了一台大办公桌大小的小型计算机。开发和运行程序的方式也在改变。在此之前,一台计算机通常只配有一名操作员,并被限制在一个区域内。程序员在另一个房间或建筑中的打孔机上编写程序。然后,他们将一叠叠卡片交给电脑操作员,电脑操作员将它们装入读卡器,并在电脑上按顺序编译和运行程序。然后,程序员返回,得到以新的卡片堆叠或打印输出的形式表示的输出结果。这种操作模式也称为批处理,可能会导致程序员等待数天,得到包括错误消息在内的操作结果。
处理速度和内存容量的提高使得计算机科学家能够开发出第一个分时操作系统。编程语言LISP 的创建者麦卡锡认识到,一个程序可以自动化人类系统操作员执行的许多功能。当内存(包括磁性二级存储)变得足够大,可以同时容纳几个用户的程序时,它们可以被安排并行处理。与程序相关联的每个进程将运行一段时间,然后将CPU 交给另一个进程。所有的活动进程将由CPU 重复循环,直到完成。
几个用户现在可以通过在连接到一台计算机的独立终端输入命令来同时运行自己的程序。随着处理器速度的不断提高,每个用户都产生了分时计算机系统完全属于自己的错觉。
到20 世纪60 年代末,程序员可以在终端输入程序,也可以看到程序输出立即显示在CRT (阴极射线管)屏幕上。与它的前身相比,这种新的计算机系统不仅交互性强,而且用户更容易使用。
许多相对中小型的机构(如大学)能够负担得起计算机,这些机器不仅用于数据处理和工程应用,还用于计算机科学新的快速发展领域的教学和研究。
1.3.5 个人计算和网络(1975 ~1990)
20 世纪60 年代中期,斯坦福研究所(SRI)的计算机科学家道格拉斯·恩格尔巴特第一个意识到摩尔定律的终极含义之一:最终,也许在一代人的时间内,硬件组件将变得足够小,并且足够便宜,能够为每个人批量生产一台个人计算机。这些个人电脑将采取什么形式?其所有者将如何使用它们?20 年前,1945 年,恩格尔巴特在《大西洋月刊》上读到了一篇题为“我们可能认为”的文章,这篇文章已经提出了这个问题并给出了一些答案。作者——麻省理工学院的科学家范尼瓦尔·布什——预测,计算设备将成为信息的储存库,最终成为所有人类知识的储存库。计算设备的所有者将通过使用指点设备浏览内容来查阅内容,并且他们几乎可以随意向知识库提供信息。恩格尔巴特赞同个人电脑的主要目的是提高人类智力的观点,他在职业生涯的剩余时间里设计了能够实现这一目标的电脑系统。
在20 世纪60 年代后期,恩格尔巴特制造了第一个定点设备,或称鼠标。他还设计了在位图显示屏上显示窗口、图标和下拉菜单的软件。他演示了计算机用户不仅可以在键盘上输入文本,还可以直接操纵屏幕上代表文件、文件夹和计算机应用程序的图标。
但是对恩格尔巴特来说,个人计算并不意味着独立计算。他参加了第一次将计算机连接到网络的实验,他相信不久人们将会使用计算机来交流、分享信息,并在团队项目上进行合作。
恩格尔巴特在SRI 的一台小型计算机上开发了他的第一个实验系统,他称之为NLS(在线系统)增强系统。20 世纪70 年代初,他搬到施乐帕洛阿尔托研究中心,与艾伦·凯领导的团队合作开发了第一个台式计算机系统。这个被称为Alto 的系统具有恩格尔巴特增强功能的许多特征,还有电子邮件和一个功能正常的超文本(万维网的前身)。凯的团队还开发了一种名为Smalltalk 的编程语言,旨在为新电脑创建程序,并向儿童教授编程。凯的目标是开发一台大笔记本大小的个人电脑,他称之为Dynabook。不幸的是,施乐公司的管理层对复印机比对凯的研究小组远见卓识的工作更感兴趣。然而,一位名叫史蒂夫·乔布斯的年轻企业家参观了施乐实验室,并看到了Alto 在运作。大约十年后的1984 年,苹果电脑公司——史蒂夫·乔布斯创立的著名公司——推出了Macintosh,这是第一款成功批量生产的带有图形用户界面的个人电脑。
当凯的团队忙于在他们的研究实验室里构建未来的计算机系统时,几十名业余爱好者聚集在旧金山附近,成立了Homebrew 电脑俱乐部,这是第一个个人计算机用户团体。他们聚在一起分享个人计算的想法、程序、硬件和应用。第一台大规模生产的个人电脑Altair 出现于1975 年。Altair 包含英特尔的8080 处理器——第一个微处理器芯片。但是从外部来看,Altair 的样子和行为更像早期电脑的微缩版,而不是Alto。程序及其输入必须通过翻转开关输入,输出由一组灯显示。然而,Altair 小到足以让个人计算爱好者带回家,最终,人们又发明了输入/ 输出设备来支持文本和声音的处理。
Osborne 和Kaypro 是首批批量生产的交互式个人电脑。他们夸耀自己的显示屏和键盘很小,软盘驱动器用于加载系统软件、应用软件和用户数据文件。早期的个人计算应用是文字处理器、电子表格和游戏,如Pac - Man 和Space war !。这些计算机还运行CP / M (微机控制程序),这是第一个基于PC 的操作系统。
20 世纪80 年代初,一位名叫比尔·盖茨的大学辍学者和他的合作伙伴保罗·艾伦开发了他们自己的操作系统软件,他们称之为MS -DOS(微软磁盘操作系统)。然后,他们与大
型计算机制造商IBM 达成协议,为该公司打算批量生产的新系列电脑提供MS-DOS。这项交易对盖茨的公司微软来说是非常有利的。微软每售出一台电脑都会收到一笔费用,而且在提供运行于其操作系统上的应用软件方面也有领先优势。IBM PC 被迅速销售给个人和机构,使MS -DOS 成为世界上使用最广泛的操作系统。几年之内,盖茨和艾伦成为亿万富翁,十年之内,盖茨成为世界首富,并且一直持续了13 年。
同样在20 世纪70 年代,美国政府开始支持网络的开发,将军事设施和研究型大学的计算机连接起来。第一个这样的网络被称为ARPANET (高级研究项目代理网络),连接了SRI、加州大学洛杉矶分校、加州大学圣巴巴拉分校和犹他大学的四台计算机。鲍勃·梅特卡夫是施乐公司凯团队的研究员,他开发了一种名为以太网的软件协议,用于运行计算机网络。以太网允许计算机在组织内部的局域网(LAN)中通信,也允许计算机通过广域网(WAN )与其他组织中的计算机通信。到20 世纪80 年代中期,ARPANET 已经发展成为我们现在所说的互联网,连接了世界各地大型机构、小型组织和个人拥有的计算机。
1.3.6 咨询、通信和电子商务(1990 ~2000)
20 世纪90 年代,计算机硬件成本持续下降,处理速度和内存容量飙升。诸如光盘(CD)和数字视频光盘(DVD)之类的光学存储介质被开发以用于大容量存储。图像、声音和视频的数字化和计算处理变得可行和广泛。到2000 年年底,整个电影都可以用数字设备拍摄、制作和回放。《玩具总动员》是第一部完全由电脑制作的长篇动画电影,出现于1995年。创造逼真的整体环境三维动画的能力催生了一种叫作虚拟现实的新技术。新的设备出现了,如平板扫描仪和数码相机,这些设备可以与更传统的麦克风和扬声器一起使用,以支持几乎任何类型信息的输入、数字化和输出。
台式机和笔记本电脑现在不仅可以完成有用的工作,还可以为用户提供新的个人表达方式。在这十年中,计算机作为通信工具快速崛起,包括电子邮件、即时消息、公告栏、聊天室和万维网。
也许这一时期最有趣的故事是关于万维网的创造者蒂姆·伯纳斯-李。20 世纪80 年代末,在瑞士日内瓦欧洲核子研究中心从事研究的理论物理学家伯纳斯-李开始研究一些利用计算机共享信息的想法。计算机工程师已经将计算机与网络连接了几年,在世界各地的研究团体中交换文件和收发电子邮件已经很普遍了。然而,硬件、操作系统、文件格式和应用程序的巨大差异仍然使得不擅长编程的用户难以访问和共享这些信息。伯纳斯-李对创造一种共享信息的通用媒体感兴趣,这种媒体不仅对科学家来说很容易使用,而且对任何其他能够操纵键盘和鼠标并在显示器上查看信息的人来说也很容易使用。
伯纳斯-李熟悉范尼瓦尔·布什对网络咨询系统的设想,恩格尔巴特关于自然语言系统扩充的工作,以及第一个广泛使用的超文本系统。其中一个系统——苹果电脑的HyperCard——将超文本的范围扩大到了超媒体。HyperCard 允许作者不仅将文本,还将图像、声音、视频和可执行应用程序组织成链接信息网络。然而,HyperCard 数据库仅位于独立计算机上,这些链接无法将超高速缓存数据从一台计算机传送到另一台计算机。此外,支持软件只在苹果电脑上运行。
伯纳斯-李意识到网络可以将超媒体系统的覆盖范围扩展到任何连接到网络的计算机,从而使他们的信息在全球范围内可用。为了保持其与特定操作系统的独立性,新媒体需要有分发和呈现信息的通用标准。为了确保这种中立和独立,任何私人公司或政府都不能拥有这种媒体并规定标准。
伯纳斯-李于1992 年为这种新媒体(我们现在称之为万维网)构建了软件。该软件使用了许多现有的机制在互联网上传输信息。人们通过在称为Web 服务器的计算机上发布文件来为Web 贡献信息。这些计算机上的Web 服务器软件负责响应查看存储在Web 服务器上的信息的请求。为了在网络上查看信息,人们使用一种叫作Web 浏览器的软件。为了响应用户的命令,Web 浏览器通过互联网向适当的Web 服务器发送信息请求。服务器通过将信息发送回浏览器的计算机(称为Web 客户端)进行响应,在浏览器中显示或呈现信息。
尽管伯纳斯-李写了第一个网络服务器和网络浏览器软件,但他做出了另外两项更重要的贡献。首先,他设计了一套称为HTTP(超文本传输协议)的规则,允许任何服务器和浏览器相互对话。其次,他设计了一种语言——HTML(超文本标记语言),它允许浏览器将信息结构化显示在网页上。然后,他免费向任何人提供所有这些资源。
伯纳斯-李发明并免费开放了这种通用信息媒体,这是一项真正了不起的成就。今天,全世界有数百万台Web 服务器在运行。任何拥有适当培训和资源的人——公司、政府、非营利组织和个人——都可以启动一个新的Web 服务器或在其中获得空间。现在,Web 浏览器软件不仅在台式机和笔记本电脑上运行,也在手机等手持设备上运行。
互联网、网络和相关软件技术的发展也在20 世纪后半叶改变了制造业、零售业和金融业。计算机支持的自动化极大地提高了生产率(同时消除了许多人的高薪工作)。公司建立并完善了从原材料到成品再到零售的货物生产和分销链,这些链的成本效益和范围越来越大。计算机技术在很大程度上促进了沃尔玛等大型超市的扩张和亚马逊等在线商店的崛起(同时也迫使许多当地零售商停业,并创造了一批没有福利的兼职员工)。
使网上商店无处不在的被称为Web 应用的技术,在向人们提供软件服务的方式上带来了一场革命。人们可以通过Web 浏览器获得对特定服务的访问,而不是购买和运行安装在自己计算机上的特定应用软件。提供此服务的Web 应用程序运行在提供商营业地的远程计算机或服务器上。Web 浏览器为数百万用户扮演了客户端、前端或用户界面的角色,以访问给定服务的同一服务器应用程序。客户端/ 服务器应用程序已经被用于电子邮件、布告板和互联网上的聊天室,所以这项技术在出现时只需简单地部署在网络上。
这十年的最后一次重大发展发生在斯坦福大学的一个计算机实验室,两位研究生谢尔盖·布林和拉里·佩奇开发了索引和搜索网络的算法。他们的工作成果给词典增添了一个新动词:谷歌。今天,世界经济和研究的大部分都依赖于谷歌的各种搜索平台。
1.3.7 移动应用和普适计算(2000 ~现今)
随着上一个千年临近尾声,计算机硬件在尺寸和成本上继续缩小,并且提供了更多的内存和更快的处理速度。对数百万人来说,笔记本电脑变得更小、更快、更实惠。第一个被称为个人数字助理(PDA)的手持计算设备开始出现。这些设备的应用仅限于简单的视频游戏、地址簿、待办事项列表和笔记记录,它们必须通过电缆连接到笔记本电脑或台式电脑以传输信息。
与此同时,随着数百万人开始使用第一部手机,蜂窝技术的应用变得广泛。与今天的智能手机相比,这些允许通过简单的机械键盘进行通话的设备还显得“愚蠢”。但是蜂窝技术为即将到来的发展提供了基础。大约在同一时间,无线技术支持计算机通过空中与具有互联网连接的基站通信。移动计算和无处不在的计算的条件已经具备,只等待那些能让它们有用和受欢迎的设备和应用。
没有人能比史蒂夫·乔布斯(苹果电脑的创始人)更好地预见到移动计算可能带来的设备和应用类型。在他生命的最后十几年里,乔布斯从苹果公司引进了几款设备和技术,不仅革新了计算机,也革新了人们从事文化追求的方式。这些设备是:iPod,最初是一个数字音乐播放器,但后来演变成一个手持通用计算设备;iPhone,为iPod 增加了手机技术及功能;iPad,实现了艾伦·凯个人笔记本电脑的梦想。所有这些设备都使用触摸屏和语音识别技术,这消除了对体积庞大的机械键盘的需求。
相关的软件技术以苹果的iLife 套件的形式出现,这是一组应用程序,允许用户组织各种类型的媒体(音乐、照片、视频和书籍)。苹果的iTunes 、iBooks 和App Stores,这些供应商网站允许开发者销售移动媒体和应用程序。十年来让用户访问Web 应用程序的Web 浏览器成为移动计算领域的另一种应用程序。
新的千年见证了数字领域的另一个重要补充:社交网络应用。尽管各种互联网论坛(如聊天室和布告板系统)已经使用了几十年,但并不普遍。2004 年,哈佛大学的学生马克·扎克伯格在大学宿舍里推出Facebook,改变了这一切。该应用程序允许学生加入网络共享他们的个人资料,发布消息、照片和视频,并且通常作为“朋友”进行交流。Facebook 的规模迅速扩展到超过10 亿用户。社交网络技术现在包括许多其他变体,例如LinkedIn、Twitter 、Tumblr 、Flickr 和Instagram。
最后,我们还要提一下被称为大数据的技术的兴起。政府、企业和黑客出于各种目而不断监控互联网流量,这个“点击流”可以被“挖掘”来了解用户的偏好和兴趣。例如,在线商店可能会在用户上网购物时看到类似的产品后,立即在他的Facebook 页面上做广告。数据科学领域的研究人员已经发明了处理大量数据以发现趋势和预测结果的算法。
总结一下这段不那么短暂的历史,一个趋势将过去几十年的计算联系在一起:快速进步。过程和事物已经变得自动化、可编程、更小、更快、高度互联,并且易于可视化和解释。
如果你想了解更多关于计算历史的信息,请参考本章末尾列出的文献。我们现在开始介绍Python 编程。
1.4 开始Python 编程
圭多·范·罗瑟姆在20 世纪90 年代早期发明了Python 编程语言。Python 是一种高级通用编程语言,用于解决现代计算机系统上的问题。Python 语言和许多支持工具都是免费的,Python 程序可以在任何操作系统上运行。你可以从www.python.org 下载Python 及其文档和相关材料。下载和安装Python 的说明见附录A。在本节中,我们将向你展示如何创建和运行简单的Python 程序。
1.4.1 在交互式shell 中运行代码
Python 是一种解释语言,你可以在名为shell 的交互式编程环境中运行简单的Python 表达式和语句。打开Python shell 最简单的方法是启动IDLE(集成开发环境)。这是Python 安装附带的集成程序开发环境。执行此操作时,将打开一个名为Python Shell 的窗口。图1-6 显示了macOS 上的shell 窗口,在Windows 系统或Linux 系统上运行的shell 窗口看起来应该与这个相似。请注意,此屏幕截图中出现的Python 版本是3.6.1。本书假设你将使用Python 3 而不是Python 2 。这两个版本之间有很大的差异,本书中使用的许多示例不适用于Python 2。
在shell 窗口中包含一条打开消息,后面跟着一个特殊符号>>>,称为shell 提示符。shell 提示符下的光标等待你输入Python 命令。请注意,通过在shell 提示符下输入help 或从窗口的下拉菜单中选择帮助,便可以立即获得帮助。
当你输入表达式或语句时,Python 会对其进行计算并显示结果(如果有的话),然后显示新的提示符。接下来的几行显示了对几个表达式和语句的求值。
注意Python 代码中颜色的使用。IDLE 编程环境使用颜色编码来帮助读者挑选代码中的不同元素。在这个例子中,引号内的项目是绿色的,标准函数的名称是紫色的,程序注释是红色的,IDLE 对用户命令的响应是蓝色的,剩余的代码是黑色的。表1-1 列出了本书所有程序代码中使用的颜色编码方案。
Python shell 对于尝试用短表达式或语句来学习该语言的新特性以及查阅该语言的文档非常有用。要退出Python shell,你可以选择窗口的关闭框,或者按下Control + D 组合键。
本节的其余部分将探讨开发更复杂和更有趣的程序的方法。
1.4.2 输入、处理和输出
大多数有用的程序接受来自某个来源的输入,处理这些输入,然后最终将结果输出到某个目的地。在基于终端的交互式程序中,输入源是键盘,输出目的地是终端显示器。Python shell 本身就是这样一个程序,它的输入是Python 表达式或语句,它的处理会评估这些项目,它的输出是shell 中显示的结果。
程序员也可以使用打印功能强制输出一个值。使用此函数的最简单形式如下所示:
本示例向你展示了使用print函数的基本语法(或语法规则)。尖括号(< >)符号包含一种短语。在实际Python 代码中,你将使用该类型短语的示例来替换这种语法形式,包括尖括号。在这种情况下, 是任何Python表达式的简写,例如
3+4。
运行print函数时,Python 首先计算表达式,然后显示其值。在前面显示的示例中,print用于显示一些文本。下面是另一个例子:
在这个例子中,文本“Hi there”是我们希望Python 显示的文本。在编程术语中,这段文字被称为字符串。在Python 代码中,字符串总是用引号括起来。但是,print函数显示不带引号的字符串。
你还可以编写一个打印函数,该函数包含两个或多个用逗号分隔的表达式。在这种情况下,print函数会评估表达式,并在一行中显示结果,用单个空格分隔。带有两个或更多表达式的print语句的语法如下所示:
注意这个语法示例中的省略号(...)。省略号表示你可以在第一个表达式之后包含多个表达式。无论输出一个或多个表达式,print函数总是以换行符结束其输出。换句话说,它显示表达式的值,然后将光标移动到窗口的下一行。
要在与上一行相同的行上开始下一个输出,可以将表达式end="",即“用空字符串而不是换行符结束行”,放在表达式列表的末尾,如下所示:
在Python 中创建程序时,你经常希望程序向用户请求输入。你可以通过使用input 函数来做到这一点。此功能使程序停止并等待用户从键盘输入值。当用户按下return 或enter 键时,该函数接受输入值,并使其可供程序使用。以这种方式接收输入值的程序通常会将其保存以供进一步处理。
下面的示例接收来自用户的输入字符串并保存它以供进一步处理。用户的输入是黑色的。
输入功能执行以下操作:
● 显示输入提示。在这个例子中,提示是"Enter your name:"。
●接收在键盘上输入的称为字符的击键字符串,并将该字符串返回给shell。输入函数如何知道使用什么作为提示?括号中的文本"Enter your name:"是input函数的一个参数,它告诉input函数如何用于提示。参数是函数完成工作所需的信息。通过将函数返回的字符串分配给变量name 来保存。具有输入功能的赋值语句的形式如下:
变量标识符简称变量,它只是一个值的名称。当变量在input语句中收到它的值时,变量就会引用这个值。如果用户在最后一个示例中输入了名称
“Ken Lambert”,变量名的值如下所示:
input函数总是根据用户的击键建立一个字符串并将其返回到程序中。输入代表数字的字符串后,程序员必须将它们从字符串转换成合适的数字类型。在Python 中,为此有两个类型转换函数,分别称为int(整数)和float(浮点数字)。下一个例子输入两个整数并显示它们的总和:
注意,调用int函数时,输入函数会返回每个结果。将这两个数字相加,然后输出它们的总和。表1-2 总结了本节介绍的函数。
1.4.3 编辑、保存和运行脚本
虽然在shell 提示符下以交互方式尝试短Python 表达式和语句很容易,但是编写、编辑和保存文件中更长、更复杂的程序更方便。然后,我们可以在IDLE 中运行这些程序文件或脚本,也可以在操作系统的命令提示符下运行,而不打开IDLE。脚本文件也是Python 程序分发给他人的方式。最重要的是,正如你从写学期论文中知道的,文件允许你安全和永久地保存若干小时的工作。
要以这种方式编写和执行程序,请执行以下步骤:
- 从shell 窗口的“文件”菜单中选择“新建窗口”选项。
- 在新窗口中,按照希望Python 执行它们的顺序,在单独的行上输入Python 表达式或语句。
- 在任何时候,你都可以通过选择文件/ 保存来保存文件。如果要这样做,你应该使用.py 扩展码。例如,你的第一个程序文件可能被命名为myprogram. py .
- 要以Python 脚本运行此代码文件,请从“运行”菜单中选择“运行模块”或按F5 键。
步骤4 中的命令从保存的文件中读取代码并执行。如果Python 执行代码中的任何print 函数,你将像往常一样在shell 窗口中看到输出。如果代码请求任何输入,解释器将暂停以等待你的输入。否则,程序执行会在后台继续。当解释器执行完最后一条指令后,它退出并返回shell 提示符。
图1-7 显示了一个IDLE 窗口,其中包含一个完整的脚本,提示用户输入矩形的宽度和高度,计算矩形的面积,并输出结果。
脚本当脚本从IDLE 窗口运行时,它会在图1-8 所示的shell 窗口中产生与用户的交互。
与在Python 解释器的提示下直接输入程序相比,这可能是一种互动程度稍低的执行程序的方式。但是,从IDLE 窗口运行脚本将允许你构建一些复杂的程序,测试它们,并将它们保存在程序库中,以便重用或与他人共享。
1.4.4 幕后:Python 是如何工作的
无论你是将Python 代码作为脚本运行还是在shell 中交互运行,Python 解释器都会做大量工作来执行程序中的指令。这项工作可以分成一系列步骤,如图1-9 所示。
- 解释器读取Python 表达式或语句,也称为源代码,并验证其是否格式良好。在这一步中,解释器表现得像一个严格的英语老师,拒绝任何不遵守语法规则的句子。一旦解释器遇到这样的错误,它就会停止并显示一条错误消息。
- 如果Python 表达式格式良好,解释器会将其翻译成一种名为字节码的低级语言的等效形式。当解释器运行脚本时,它会将其完全翻译成字节码。
- 字节码随后被发送到另一个软件组件中执行,该组件称为Python 虚拟机(PVM)。如果在此步骤中发生另一个错误,执行也会停止,并显示一条错误消息。
■.练习
- 描述当程序员在Python shell 里输入字符串“Greetings!”时会发生什么。
- 编写一行代码,提示用户输入自己的名字,并将用户输入保存在名为name 的变量中。
- 什么是Python 脚本?
- 解释当你的计算机运行Python 程序时,幕后发生了什么。
1.5 检测和纠正语法错误
程序员在编写程序时不可避免地会犯拼写错误,Python 解释器几乎总能检测到这些错误。这种错误称为语法错误。术语语法是指在语言中形成句子的规则。当Python 在程序中遇到语法错误时,它会停止执行,并显示错误消息。Python shell 的以下示例显示了几种类型的语法错误和相应的错误消息:
第一条语句为变量Length分配一个输入值。下一条语句试图打印变量Length的值。Python 回应说这个名字没有定义。虽然程序员可能想写变量Length,但是Python 只能读取程序员实际输入的内容。这是一个很好的例子,说明一台计算机只能读取它接收的指令,而不能读取我们打算给它的指令。
下一条语句试图打印拼写正确的变量的值。但是,Python 仍然会生成错误消息。
在此错误消息中,Python 解释了这一行代码意外缩进。事实上,在print之前还有一个额外的空格。缩进在Python 代码中非常重要。在shell 提示符或脚本中输入的每一行代码必须从最左边的列开始,没有前导空格。此规则的唯一例外发生在控制语句和定义中,其中嵌套语句必须缩进一个或多个空格。
你可能会认为跟踪程序中的缩进会很痛苦。然而,作为补偿,Python 语言比其他编程语言简单得多。因此,要遇到和纠正的语法错误类型更少,要学习的语法也更少!
在我们的最后一个例子中,程序员试图添加两个数字,但是忘记了第二个数字:
在后面的章节中,你将了解更多其他类型的程序错误以及如何修复产生这些错误的代码。
■.练习
- 假设你的脚本试图打印尚未赋值的变量的值,Python解释器会有什么反应?
- 如果米兰达忘记在一行结束前完成算术表达式的代码,Python解释器会有什么反应?
- 为什么Python 代码生成的语法错误类型少于其他编程语言的代码?
1.6 拓展阅读
1.7本章小结
● 计算机科学最基本的思想之一是算法。算法是解决问题的一系列指令。计算智能体可以执行这些指令以在有限的时间内解决问题。
● 计算机科学的另一个基本思想是信息处理。实际上,现实世界对象之间的任何关系都可以表示为信息或数据。计算智能体按照算法中描述的步骤操作信息并对其进行转换。
●真正的计算智能体可以由硬件设备构成。这些设备包括中央处理单元(CPU)、存储器以及输入和输出设备。CPU 包含执行算法描述的指令的电路。内存包含代表二进制数字的开关。存储在存储器中的所有信息都以二进制形式表示。键盘和平板扫描仪等输入设备以及显示器和扬声器等输出设备在计算机内存和外部世界之间传输信息。这些设备还在二进制形式和人类可以使用的形式之间传递信息。
● 一些真正的计算机,如手表和手机中的计算机,是专门用于一小部分任务的,而台式或膝上型计算机是一种通用的解决问题的机器。
● 软件提供了在通用硬件设备上运行不同算法的手段。软件一词可以指用于开发程序的编辑器和解释器,用于管理硬件设备的操作系统,用于与人类用户通信的用户界面,以及文字处理器、电子表格、数据库管理器、游戏和媒体处理程序等应用程序。
●软件是用编程语言编写的。Python 等语言是高级语言,它们类似于英语,允许作者向其他人清晰地表达自己的算法。一种叫作“解释器”的程序将Python 语言编写的程序翻译成可以在真实计算机上执行的低级语言程序。
●Python shell 提供了一个命令提示符,用于评估和查看Python 表达式和语句的结果。IDLE 是一个集成开发环境,允许程序员将程序保存在文件中,并加载到shell 中进行测试。
●Python 脚本是保存在文件中并从终端命令提示符运行的程序。交互式脚本由一组输入语句、处理这些输入的语句和输出结果的语句组成。
●当Python 程序被执行时,它被翻译成字节码。该字节码随后被发送到Python 虚拟机(PVM)以供进一步解释和执行。
●语法是在编程语言中形成正确表达式和语句的一组规则。当解释器在Python 程序中遇到语法错误时,它会停止执行,并显示错误消息。语法错误的两个例子是对一个变量的引用,在第一个例子中,该变量还没有值,在第二个例子中,多了一个意想不到的缩进。
1.8 复习题
-
以下哪个是算法的例子?
- 字典 b. 食谱
- 一套组装公用小屋的说明 d. 文字处理器中的拼写检查器
-
以下哪项包含信息?
- 我祖母的瓷器柜 b. 一张音频光盘
- 一台冰箱 d. 一本书
- 一台运行中的计算机
-
以下哪项是通用计算设备?
- 手机 b. 便携式音乐播放器
- 笔记本电脑 d. 可编程恒温器
- 以下哪项是输入设备?
a. 扬声器 b. 麦克风 -
以下哪项是输出设备?
- 数码相机b. 键盘
- 平板扫描仪d. 显示器
-
中央处理器的目的是什么?
- 存储信息b. 接收来自人类用户的输入
- 解码并执行指令d. 将输出发送给人类用户
-
下列哪一项用编程语言翻译和执行指令?
- 编译程序b. 文本编辑器
- 加载器d. 解释器
-
以下哪一项在Python 程序中输出数据?
- 输入语句b. 赋值语句
- 打印语句d. 主函数
-
IDLE 用来做什么?
- 编辑Python 程序b. 将Python 程序保存到文件中
- 运行Python 程序d. 所有上述情况
-
在一种语言中,用于造句的一组规则被称为什么?
- 语义b. 语用
- 语法d. 逻辑
1.9 编程项目
- 打开Python shell,输入以下表达式并观察结果:
- 8 b. 8 * 2
- 8 ** 2 d. 8 / 12
- 8 // 12 f. 8 / 0
- 编写一个Python 程序,打印(显示)你的姓名、地址和电话号码。
- 在shell 提示符下评估以下代码:print("Your name is",name)。然后给name 分配一个合适的值,并再次评估语句。
- 打开一个IDLE 窗口,输入图1-7 中计算矩形面积的程序。按F5 键将程序加载到shell 中,并纠正出现的任何错误。用不同的输入测试程序至少三次。
- 修改上一题的程序来计算三角形的面积。对三角形的底边和高度给出适当的提示,并适当更改变量的名称。然后,使用公式来计算面积。从IDLE 窗口测试程序。
- 编写并测试一个计算圆的面积的程序。这个程序应该请求一个代表半径的数字作为用户的输入。它应该使用公式来计算面积,然后输出适当标注的结果。
- 编写并测试一个接受用户名(作为文本)和年龄(作为数字)作为输入的程序。程序应该输出包含用户姓名和年龄的句子。
- 在shell 提示符下使用input函数输入语句。当提示要求你输入时,请输入一个数字。然后,尝试将数字加1,观察结果,并解释发生了什么。
- 在shell 提示符下使用input函数输入语句。当提示要求你输入时,输入你的名字,观察结果,并解释发生了什么。
- 在shell 提示符下输入表达式help()。按照说明浏览主题和模块。