编程入门
一位维基教科书用户认为此页面应该分成较小的页面,涵盖更窄的子主题。 您可以通过将此大页面分成较小的页面来提供帮助。请确保遵循命名规范。将书籍分成更小的部分可以提供更多重点,并允许每个部分都能很好地完成一项工作,从而使每个人受益。 |
以下部分将介绍计算机编程中的各种概念。以下解释中存在一些简化。请不要将任何内容过于认真对待。
编程的目的是告诉计算机做什么。计算机在某些事情上比你更擅长,就像厨师在烹饪方面比你更擅长一样。告诉厨师为你做一顿饭比你自己做饭更容易。你的要求越精确,你的饭菜就越符合你的喜好。在现实生活中,大多数类似的情况允许适度的模糊性和误解。也许厨师会在捣碎土豆之前先煮一下,而不是烤一下。然而,对于计算机来说,模糊性很少被接受。程序非常复杂,如果计算机只是猜测模糊或含糊要求的含义,可能会导致非常微妙的问题,以至于你永远找不到它们。因此,编程语言被设计成只接受完全清晰和明确的语句。程序仍然可能存在问题,但责任就完全归咎于你,而不是计算机的猜测。编程中的许多困难来自必须对所有事情都做到完美的精确和详细,而不是只给出高级指令。
有些语言要求对所有事情都做到完全详细。C 和 C++ 就是这样的语言,被称为低级语言。其他语言会做出各种假设,这使得程序员可以指定更少的细节。Python 和 Basic 就是这样的语言,被称为高级语言。一般来说,高级语言更容易编程,但给你更少的控制权。控制有时很重要,例如如果你想让你的程序运行得尽可能快。大多数情况下,完全控制和速度不是必需的,随着计算机变得越来越快,高级语言变得越来越流行。在这里,我们将专门处理高级语言。低级语言通常很相似,只是完成相同的事情通常需要写更多代码行。
大多数编程语言都有语句的概念。一个语句是程序员给计算机的命令。例如
print "Hi there!"
这个命令有一个动词(“打印”)和其他细节(要打印什么)。在本例中,命令print意味着“在屏幕上显示”,而不是“在打印机上打印”。程序员要么直接将语句给计算机(在运行一个特殊的程序时输入它),要么创建一个包含命令的文本文件。你可以使用像 Notepad 这样的程序创建一个名为“hi.txt”的文件,在其中放入上面的命令,然后将该文件给计算机。(如何完成所有这些操作的细节是特定于语言和系统的,因此这里不会介绍。这只是一个对概念的介绍。)
如果你在文件中有多个命令,每个命令将按顺序从上到下执行。因此,该文件可能包含
print "Hi there!" print "Strange things are afoot..."
计算机将依次执行这些命令。在编程时能够“扮演计算机”非常有价值。问问自己,“如果我是计算机,我会对这些语句做什么?”如果你不确定答案,那么你很可能写出错误的程序。停止并检查你正在使用的编程语言的手册。
在上面的例子中,计算机将查看第一个语句,确定它是一个print语句,查看需要打印的内容,并将该文本显示在计算机屏幕上。它将看起来像这样
Hi there!
请注意,引号不在那里。它们在程序中的作用是告诉计算机文本从哪里开始和结束,就像在英语散文中的作用一样。然后,计算机将继续执行下一个语句,执行其命令,屏幕将看起来像这样
Hi there! Strange things are afoot...
当计算机到达文本文件末尾时,它将停止并等待进一步的指令。根据使用的编程语言,有许多不同类型的语句。例如,可能会有一个beep语句,导致计算机在其扬声器上发出蜂鸣声,或者一个window语句,导致一个新的窗口弹出。
此外,语句的编写方式将根据编程语言而有所不同。Python 编程语言使用类似于上面的语句。在 C 中,你会写
puts("Hi there!"); puts("Strange things are afoot...");
请注意一些差异
- 参数(引号中的文本,print用来确定要显示的内容)用括号包围。
- 每个语句都以分号结尾。
- 动词print被称为puts,表示“放置字符串”。单词字符串是计算机术语,指一些文本。它来自“字母串”。“put”的意思是“放在屏幕上”。
这些差异相当肤浅。像前两个这样的规则集被称为编程语言的语法。动词集被称为它的库。
所有计算机语言都有语法,创建正确语句的规则,就像自然语言一样。例如,大多数句子以句号或句点结束。同样,源代码中的语句通常以分号结尾,但许多语言没有这个要求,所以了解你正在编程的语言的语法很重要。例如,如果你想让计算机显示两个不同的东西,你可以写
print "I have a dog. His name is Bort."
或者你可以写
print "I have a dog. " + "His name is Bort."
第二个例子有两个字符串,每个字符串都用引号括起来。它们之间有一个加号(+)符号,这意味着“将两个字符串连接在一起,将它们变成一个字符串。”(连接两个字符串被称为串联。)上面的两个语句将显示相同的内容
I have a dog. His name is Bort.
在上面的例子中,你没有理由使用一个+和两个字符串,因为你可以只使用一个字符串,就像第一个例子中的那样,但在下面,将会有字符串串联是必要的的情况。Python 和 Java 语言使用加号(+)进行字符串串联,Perl 和 PHP 使用句点(.),Visual Basic 使用与号(&)。同样,这些差异是肤浅的;重要的是字符串串联的概念以及语言语法来完成像串联这样的事情。在你的脑海中区分一个底层概念和一个特定语言表达该概念的方式。
当程序被编译或转换成可执行程序时,它们会被一个解析器(相当于校对者)分析,以确定语法是否正确。假设程序的源代码在语法上是正确的,编译器将继续分析源代码,以确定是否存在任何语义错误。
语义指的是计算机程序的含义或逻辑。两个语法正确的语句可以独立地完美地表达意思,但当它们放在一起时,可能就没有意义了。有时,这些逻辑上的缺陷可以被编译器检测到,被称为编译时错误,但通常这些错误在程序执行时出现,被称为运行时错误。
观察以下对话
Alice: Terrible news. Carl's wife was in a car accident. Bob: Oh, that is terrible. Send some nice flowers and get everyone to sign a card. Alice: Sure. Oh, and Dan called in sick again. Bob: Not again. Send him a pink slip.
这段对话意义完美,合乎逻辑。这段对话展示了语义的良好、一致的用法。
现在观察这段对话
Alice: Terrible news. Carl's wife was in a car accident. Bob: Not again. Send him a pink slip. Alice: Sure. Oh, and Dan called in sick again. Bob: Oh, that is terrible. Send some nice flowers and get everyone to sign a card.
尽管这段对话包含与上一段对话完全相同的句子,但它却有着截然不同的含义。人类可能会改变语法和结构的规则来确定对话的意图,但计算机没有那么灵活。因此,使用正确的语法和良好的语义来正确地向计算机传达你想要它做什么非常重要。但要理解,第一次对话可以重新排列,仍然具有相同的含义,或者可以用不同的句子来表达相同的想法。从这个意义上说,有很多不同的方式可以编写相同的程序。
假设你有一个关于你的狗的程序。它可能看起来像这样
print "I have a dog. It is called Bort." print "Bort likes to eat dog food." print "My children and Bort get along very well." print "My dog Bort barks at my neighbor, whose name is also Bort."
你可能会这样继续一段时间,让计算机显示关于你狗的许多有趣的事情。如果有一天,你改变了你狗的名字,或者想要谈论你另一只狗,或者把这个程序给了朋友,他们想把它改成他们的狗,你必须浏览整个程序,并将所有出现的 "Bort" 改成新名字。你可以使用文本编辑器的查找和替换功能来完成这项工作,但这样做很繁琐,你可能会犯错误。例如,你可能会不小心替换了邻居的名字,而你只是想改变狗的名字。
编程语言通过让你只写一次狗的名字,然后使用标签来引用它,来解决这个问题。这有点像在自然语言中使用代词。所以你可以写
dog = "Bort"
如果你在“扮演计算机”,并且遇到了上面的语句,你会想,“记住字符串 "Bort",每当使用单词 dog 时,就用 "Bort" 来替换它”。这被称为 赋值语句,因为你正在为单词 dog 赋予含义。接下来的语句可以写成
print dog
注意这里没有引号。你并不想直接打印单词 "dog",而是希望计算机记住它之前与这个单词关联的字符串。这有点像在说 "他说他的年龄" 和 "他说,‘他的年龄’" 之间的区别。在第一种情况下,它是一个数字,而在第二种情况下,它是单词 "他的年龄"。单词 dog 是一个 变量。它是一个符号,计算机用它与其他东西关联起来,在这种情况下是单词 "Bort"。我们原来的程序现在可以写成
print "I have a dog. It is called " + dog + "." print dog + " likes to eat dog food." print "My children and " + dog + " get along very well." print "My dog " + dog + " barks at my neighbor, whose name is Bort."
注意,这里需要使用字符串拼接(使用加号),因为有时我们需要使用引号(表示文字文本),而有时我们不需要(表示变量)。计算机会看到一个像这样的语句
print dog + " likes to eat dog food."
首先用字符串 "Bort" 替换单词 dog
print "Bort" + " likes to eat dog food."
然后拼接字符串
print "Bort likes to eat dog food."
然后执行语句,在屏幕上显示出来
Bort likes to eat dog food.
还要注意,邻居的名字没有被对 dog 的引用替换。变量 dog 指的是狗的名字。这就是使用变量的意义所在:跟踪特定的概念。你可以使用不同的变量来跟踪邻居的名字
neighbor = "Bort"
并将我们程序的最后一行改为
print "My dog " + dog + " barks at my neighbor, whose name is " + neighbor + "."
这样,你就可以很容易地在文件开头更改你狗或邻居的名字,程序的其余部分将正常运行。我从这一行中删除了单词 "也",因为现在我们使用了变量,我不能再确定这两个名字是否相同。我不想更改其中一个名字,然后让我的程序仍然在里面显示 "也"。稍后我们将看到一种只在两个名字相同时显示 "也" 的方法。
重要的是要记住关于变量的两个事情。首先,变量必须在使用之前设置。所以你必须写
dog = "Bort" print dog
而不是
print dog (Wrong!) dog = "Bort"
在“扮演计算机”时,记住你必须逐个地、按照从上到下的顺序查看每条语句。在上面的第二个例子中,你首先会遇到 "print dog" 语句,并且不知道变量 dog 指的是什么。不同的语言在遇到这个问题时会有不同的反应。有些语言只是假设变量是一个空字符串(""),但大多数语言会停止程序并报告错误。
其次,当你“扮演计算机”,并且看到正确程序的第二行
dog = "Bort" print dog
非常重要的是,你不能“向上返回”到第一行去查看 dog 指的是什么。第一行早已消失不见了。你只能一次查看一行,并且始终按顺序查看。第一行会在某个地方(在内存中)做一个记录,表明 dog 指的是 "Bort",但随后这一行本身就会被遗忘。第二行检查内存,并从那里获取变量的含义,而不是直接从第一行获取。这似乎是一个微不足道的区别,但我们稍后会以更复杂的方式使用变量,而不能“向上返回”去查找变量设置的地方;你需要将变量及其值视为存储在内存中。
单词 variable 意味着变量可以改变,而且它们确实可以改变。你可以编写以下程序
dog = "Bort" print "My first dog was called " + dog + "." dog = "Milou" print "And my second dog was called " + dog + "."
计算机将看到第一行,将字符串 "Bort" 与变量 dog 关联起来,在第二行中使用这个字符串,在第三行中将变量 dog 的关联改为 "Milou",并在第四行中使用新的关联。在内存中,变量 dog 只能与一个字符串关联。上面的第三行用新的关联替换了旧的关联。第二行和第四行查看内存,获取与 dog 关联的数字,并且在每个语句中,值都不同,因为内存中的值在程序执行到那个点时是不同的。你会看到
My first dog was called Bort. And my second dog was called Milou.
数学
[edit | edit source]当计算机看到一个数学表达式时,它会自动执行算术运算。例如,你可以写
print 5 + 6
再次注意,这里没有引号。如果有引号,计算机会直接理解并打印 "5 + 6"。加号被称为 运算符,因为它对其他值执行操作。当计算机看到上面的行时,它会执行算术运算,得到
print 11
执行语句只会打印数字
11
注意,以下两个语句将显示相同的内容
print 11 print "11"
只是在第一种情况下,计算机知道它是一个数字,而在第二种情况下,它只是一个字符串。有时这种区别很重要,但现在我们可以忽略它。数学运算可以变得非常复杂
print (5 + 12) * 9 / 14
计算机会一步一步地执行算术运算,就像你在脑海中做的那样。它会先进行加法,因为它在括号中
print 17 * 9 / 14
然后进行乘法,因为它在左边
print 153 / 14
然后进行除法
print 10
如果你运行原始行,你会看到这些
10
注意,153 除以 14 实际上是 10.928 之类的数字,但计算机打印的圆形数字低于实际值。这是因为大多数语言处理两种类型的数字:整数和实数。 整数 是圆形数字,就像上面的那些。 实数 是带有小数点的数字,比如 10.928。当计算机看到一个完全使用整数的表达式时,它会继续使用整数来进行运算,即使结果实际上应该是实数。如果我们写
print (5.0 + 12.0) * 9.0 / 14.0
那么计算机将使用实数进行运算,我们将会看到打印出类似这样的内容
10.9285714286
这是计算机历史发展中一个奇怪的结果。它会导致奇怪的结果,比如这行
print 1 / 2
显示 "0" 而不是预期的 "0.5"。有时当前的行为是可取的,但通常不是,你应该牢记整数和实数之间的区别。还要注意,以上关于整数和实数的规则适用于大多数常用的编程语言,但每种语言都可以自由地制定自己的数字处理规则,你可能有一天会使用一种行为不同的语言,例如将 "1 / 2" 的结果改为 "0.5"。
变量可以用来表示数字和字符串。你可以写
x = 5 print x
来打印 "5"。或者你可以写
age = 33 print age * 2
来计算你年龄的两倍。再次,第一行在内存中创建了一个关联,将名为 age 的变量与数字 33 关联起来。第二行查看内存,获取与 age 关联的数字,并执行算术运算。注意,第一行不是代数。它不是一个使 age 和数字 33 相等的方程。它是在将值 33 赋值 给变量 age。当你看到一行像这样的代码时,这个区别很重要
x = x + 5
上面的行在代数中是不可能的。 x 的值不可能等于 x 加 5 的值。但在编程语言中,这行代码的意思是,“在内存中找到变量 x 的值,在它上面加上 5,然后将结果与变量 x 关联起来”。 x 同时出现在等号右边的数学表达式中,以及作为存储结果的地方,这一点无关紧要。它的值在数学表达式中 先 被使用,然后结果才被存储回变量。下面是另一个例子
x = 5 y = x + 2 print x print y
你会得到
5 7
但现在如果你写
x = 5 y = x + 2 x = 10 print x print y
你会得到
10 7
逐行查看并“扮演计算机”,说服自己为什么上面的代码会这样运行。如果你需要,可以使用一张纸来跟踪 x 和 y 变量。如果上面的内容不清楚,请停止并重新阅读本节或关于变量的那一节。这对新手程序员来说是一个非常常见的障碍。
你可能已经注意到,我们使用加号(+)符号来表示“字符串拼接”和“数值加法”。这样做是可以的,通常也很清楚,但计算机应该如何处理这样的语句
print "5" + 6
应该将数字 5 和 6 加在一起得到 11 吗?应该将字符串 "5" 与字符串 "6" 拼接起来得到 "56" 吗?应该让计算机停止并报告错误吗?每种语言都以不同的方式处理这种歧义。在 Python 中,上面的行将是一个错误。你必须明确地告诉计算机你想要哪种解释。在 Java 中,"6" 将被转换成一个字符串,从而得到字符串 "56"。在 Perl、PHP 和 Visual Basic 中,字符串拼接运算符不是加号,而是 Perl 和 PHP 中的点,以及 Visual Basic 中的与号,所以根据使用的运算符,始终可以清楚地知道需要做什么。
条件语句
[edit | edit source]假设我们有一个简单的程序,用来显示你的年龄
age = 25 print "You are " + age + " years old."
如果你运行了这个程序,它会显示
You are 25 years old.
明年你可以把第一行改为“age = 26”,程序的输出就会相应更新。实际上,你可以把这个程序给任何人,他们都可以修改第一行,这样第二行就会打印出正确的年龄。等你满30岁了,你可能想这样修改它
age = 30 print "You are " + age + " years old." print "Your warranty has expired!"
这样可以正常工作,但如果你现在把它给了一个25岁的人,他们不仅要修改第一行,还要记得删除第三行。但是为什么要强迫人类删除第三行呢?计算机应该能够根据age的值自动显示或不显示第三行。我们可以使用“if”语句告诉计算机这样做
age = 30 print "You are " + age + " years old." if age > 29: print "Your warranty has expired!"
让我们再“扮演计算机”:当你到达第三行时,你会看到age这个词,意识到它是一个变量,并从内存中获取它的值(30)(它存储在第1行)
if 30 > 29:
这行说,“如果 30 大于 29,则执行缩进的语句。如果不是,则跳过缩进的语句。” 由于 30 大于 29,因此会执行缩进的语句,笑话就会显示在屏幕上。如果一个朋友将第一行更改为“age = 25”,第三行将比较 25 与 29,并且由于 25 不大于 29,因此第四行将被跳过。
这是一个条件。第四行是否运行取决于第三行上的数学表达式。该表达式可以更复杂,例如
if age >= 40 and age < 50: print "You are in your forties."
The>=符号表示“大于或等于”。这里只有当年龄在40到49岁之间时,“print”行才不会运行。你也可以放多个缩进的语句
if age >= 50 and age < 60: print "You are in your fifties." print "Mid-life crisis yet?"
如果该人的年龄在50到59岁之间,这两行都会显示;否则都不会显示。现在请注意,如果用户的年龄是1,我们原始程序的第二行将显示语法错误
You are 1 years old.
应该是“年”,而不是“年”。我们可以使用条件来修复这个错误
age = 25 if age == 1: print "You are " + age + " year old." if age != 1: print "You are " + age + " years old."
The==表示“等于”。有两个等号是为了将其与赋值语句区分开来,赋值语句使用单个等号(如我们程序的第一行)。这与我们在上面写过的计算机语言总是希望对意图完全清楚有关。The!=表示“不等于”。想想带斜线的等号的数学符号,然后想象感叹号是那个斜线。现在如果你把age设置为1,你会得到这个
You are 1 year old.
这是正确的。如果age不等于1,那么第一个“print”将被跳过,第二个将运行,显示带有复数“years”的文本版本。通常我们希望在条件为真(如“age == 1”)时执行一项操作,而在条件不为真(“age != 1”)时执行另一项操作。因此,计算机语言有一个快捷方式,可以避免你必须用反向条件重新键入整个“if”语句。你只需这样写
age = 25 if age == 1: print "You are " + age + " year old." else: print "You are " + age + " years old."
这意味着,“如果 age 是 1,则运行第一个 print 语句。如果不是(否则),则运行第二个 print 语句。” 同样,你可以在第一个部分或第二个部分中放置多个语句
age = 25 if age == 1: print "You are " + age + " year old." print "You're an infant!" else: print "You are " + age + " years old." print "You're not an infant."
现在你可以把这个程序给别人,他们只需要改变第一行,就可以得到几行关于他们的准确文本。你可以想象这可以变得任意复杂,测试非常复杂的条件。考虑这个
age = 25 if age == 1: print "You are " + age + " year old." print "You're an infant!" else: print "You are " + age + " years old." if age < 25: print "You're young." else: print "You're mature!"
这被称为“嵌套if”。第二个“if”(将age与 25 比较的那个)是嵌套(在)第一个“if”中。由于它是缩进的,所以只有在第一个条件(“age == 1”)不为真的情况下,才会运行第二个“if”。如果age实际上是1,第一个“print”将运行,整个第二个部分,包括第二个“if”,都将被跳过。因此,程序只显示“You're an infant!” 或 “You're young.” 或 “You're mature!” 之一。你应该用各种age值(如 1、5、25 和 30)来“扮演计算机”运行这个程序。
条件非常有用。在我们的例子中,每个人都可以通过在修改第一行时添加或删除“print”语句来实现(尽管不方便),但在现实中,age的值来自其他地方,例如表单或数据库,程序必须按原样运行,不作修改,并显示它可能获得的任何age值的正确文本。
我们可以看一下 C 中的条件语句,再次证明基本概念在不同的编程语言中只有细微的差别
if (age > 29) puts("Your warranty has expired!");
请注意这些差异:条件周围有括号;“print”被替换为“puts”,与以前一样;要显示的文本用括号包围;并且在“puts”语句的末尾有一个结束分号。如果你想显示多行,你需要这样写
if (age >= 50 && age < 60) { puts("You are in your fifties."); puts("Mid-life crisis yet?"); }
请注意这两个额外的差异:“and”在条件中被替换为“&&”; 并且在一对“puts”语句周围有花括号。在 C(以及从 C 派生的语言,如 C++、Java 和 C#)中,缩进被忽略,因此“if”语句将假定只有紧随其后的语句会被有条件地运行。如果你想要多个语句,你必须用花括号将它们分组,以告诉语言所有这些语句都是有条件地运行的。在我们上面的 Python 类语言中,缩进用于告诉哪些语句在“if”和“else”行的控制之下。
输入
[edit | edit source]在上面的例子中,年龄直接放在源代码中,在第1行
age = 25
这被称为硬编码年龄。硬来自于这样编写程序后,年龄永远是25。如果用户想用不同的年龄运行程序,他们需要修改源代码。但这假设他们理解编程。由于大多数用户不理解编程,我们实际上希望简单地询问用户他们的年龄,这样他们就永远不需要看到源代码。
我们可以使用这样的行
age = input()
输入意味着将信息放入计算机。输出与之相反,就像我们一直在使用的print语句。
所以我们现在的程序看起来像这样
print "What is your age?" age = input() if age == 1: print "You are " + age + " year old." else: print "You are " + age + " years old."
当用户运行程序时,他们不会立即看到“You are …”文本,而是首先看到这个
What is your age?
系统似乎会停止。然后用户可以输入他们的年龄,按回车键,程序会像以前一样继续运行,age变量被设置为用户输入的任何数字。
你可能对input后面的括号很好奇。如果你没有它们,像这样
age = input
input这个词看起来很像一个变量。由于计算机总是希望完全清楚地说明需要做什么,因此我们添加括号来表示,“这不是一个变量,而是一个命令。做一些聪明的事情。”input()实际上是一个函数。我们将在后面讲解函数,但现在你可以把它们想象成做有趣的事情(比如从键盘获取数字)并使某个值可用的代码片段(在本例中,用于将值赋给age)。当计算机看到这行
age = input()
它首先看到函数input(),做聪明的事情(从键盘获取一个数字),并用它获得的值替换函数
age = 25
(如果用户输入25)。然后赋值像以前一样继续,将值 25 存储到内存中,并将其与age这个词关联起来。
循环
[edit | edit source]假设我们想编写一个程序,询问用户他们想要重复某个短语多少次。(是的,确实需要这些愚蠢的例子。更现实的例子通常过于复杂,无法演示单个新概念。)
print "How many times?" count = input() if count == 1: print "Are we there yet?" if count == 2: print "Are we there yet?" print "Are we there yet?" if count == 3: print "Are we there yet?" print "Are we there yet?" print "Are we there yet?" if count == 4: print "Are we there yet?" print "Are we there yet?" print "Are we there yet?" print "Are we there yet?"
如果你运行这个程序,用户会被问到“How many times?”,计算机将会等待答案。用户可以输入一个介于 1 和 4 之间的数字,短语“Are we there yet?”就会显示那么多次。这个程序有几个问题。首先,它最多只能处理 4 次计数。如果用户想让它显示 5 次,程序必须扩展到处理这种情况。其次,随着情况数量的增加,很难确保程序是正确的。如果你把它扩展到 20 次,很难用文本编辑器检查第 17 次的情况是否真的有 17 行。也许你犯了个错误,只复制粘贴了 16 次。我们可以聪明点,这样重写
print "How many times?" count = input() if count >= 1: print "Are we there yet?" if count >= 2: print "Are we there yet?" if count >= 3: print "Are we there yet?" if count >= 4: print "Are we there yet?"
这有点棘手,所以一定要仔细地理解逻辑,就像计算机一样。假设count是3。第一个“if”语句将检查 3 是否大于或等于 1,并且由于它是,所以会打印第一个短语。下一个“if”将比较 count 与 2,并打印第二个短语。当count >= 3被测试时,也会发生相同的事情,因为 3 大于或等于 3。但第四次测试将不会工作,因为 3 不大于或等于 4。所以第四个短语不会显示。该短语将被显示 3 次(前三个“if”语句各显示一次),这就是我们想要的,因为count是 3。
这种新的编写程序的方式更容易验证其正确性。我们只需要确保连续“if”语句中的每个数字都比上一个数字多 1。由于每个“if”语句只打印一行,因此我们不会像第一个示例那样错误地计算“print”行的数量。但这仍然有点乏味,要扩展程序来处理更高的count值。你必须复制粘贴两行,并记住增加“if”语句中的数字。
我们可以用这个新版本让它变得更简单
print "How many times?" count = input() if count >= 1: print "Are we there yet?" count = count - 1 if count >= 1: print "Are we there yet?" count = count - 1 if count >= 1: print "Are we there yet?" count = count - 1 if count >= 1: print "Are we there yet?" count = count - 1
现在程序更复杂了,但每个“if”语句都是相同的。这使得复制粘贴变得容易得多,我们可以简单地按住 Ctrl-V 键,就可以创建一个处理非常大的count值的程序。以下是新程序的工作原理。第一个“if”语句,与以前一样,比较count与 1,如果count大于或等于 1,则打印短语。但它也做了一些其他的事情:它将count的值减 1。这个语句
count = count - 1
它做了三件事:它在内存中找到 `count` 的值,从该值减去 1,并将结果放回内存,替换掉原来的 `count` 值。所以如果 `count` 是 3,则等号右边的 `count` 将被其值替换
count = 3 - 1
然后进行算术运算
count = 2
并将新值存储到内存中,像之前一样替换掉原来的 3。你可能想知道为什么只有等号右边的 `count` 被其值替换,而左边的没有?为什么计算机不将两个 `count` 都替换成 3,像这样
3 = 3 - 1
显然这不太有用。赋值语句只在变量出现在等号(赋值)符号右边时查找变量的现有值。等号左边唯一的变量按原样使用,用于知道将哪个名称与右边算术运算的结果关联起来。
因此,在第一个短语显示后,`count` 会减 1,然后测试下一个 "if" 语句。它与之前相同,将 `count` 与 1 进行比较。假设 `count` 最初为 3。在第一个 "if" 语句中,我们将看到短语显示,`count` 将变为 2。在第二个 "if" 语句中,我们将看到短语显示,`count` 将变为 1。在第三个 "if" 语句中,我们将看到短语显示,`count` 将变为 0。在第四个 "if" 语句中,测试 "0 >= 1" 将为假,因此短语不会显示,`count` 也不会减少。无论之后有多少个 "if" 语句,`count` 的值都将保持为 0,并且不会执行任何print语句。我们将看到短语显示三次,这就是我们想要的结果,因为 `count` 最初为 3。
我们的程序现在有一个最后的问题:无论我们复制粘贴这三行代码多少次,用户总是可以输入一个比这更大的数字。你可以粘贴 500 次 "if" 语句,如果用户输入 "510",你的程序只会显示短语 500 次,每个 "if" 语句显示一次。程序将以变量 "count" 设置为 10 结束,因为还有 10 个短语需要显示,但最后的 10 个 "if" 语句将不存在。
我们可以用一个 `循环` 来解决最后一个问题,像这样
print "How many times?" count = input() while count >= 1: print "Are we there yet?" count = count - 1
这就是整个程序。具体来说,这是一个 `while 循环`,因为有几种不同的循环类型。我们删除了所有 "if" 语句,除了一个,并将 `if` 替换为 `while`。它几乎像一句英文句子:"当 `count` 大于或等于 1 时,打印此短语并将 `count` 减 1。" 让我们以 `count` 最初设置为 3 来 "模拟计算机"。计算机将到达 "while" 语句,将 3 与 1 进行比较,看到 3 大于或等于 1,显示短语,将 `count` 减 1(变为 2),并 `循环` 回到 "while" 语句。计算机将再次将 `count` 与 1 进行比较,因为 2 大于或等于 1,它将打印语句,将 `count` 减少到 1,循环回到顶部,将 `count` 与 1 进行比较,因为 1 大于或等于 1,显示短语并将变量 `count` 减少到 0。然后它将循环回到 "while" 语句,将 `count` 与 1 进行比较,因为 0 `不` 大于或等于 1,缩进的语句将不会执行,"while" 循环将结束,继续执行后面的语句。在这个程序中,没有后面的语句,所以程序将结束。每次循环称为一次 `迭代`。
有几种不同的循环类型。使用哪一种取决于你在使用的编程语言中有哪些可用功能,以及哪一种最适合你的操作。例如,在上面的示例中,我们可以打印每次迭代的 `count` 值,像这样
print "How many times?" count = input() while count >= 1: print "Are we there yet?" print count count = count - 1
运行该程序的结果如下(如果用户在提示时输入 "3")
How many times? 3 (what the user types in) Are we there yet? 3 Are we there yet? 2 Are we there yet? 1
3、2、1 是每次迭代的 `count` 值。如果我们只想向上计数怎么办?或者如果你不想修改 `count`,因为你想在程序的后面使用它?你可以使用 `for 循环`,像这样
print "How many times?" count = input() for i = 1 to count: print "Are we there yet?" print count
(`注意:` 到目前为止,我们用于示例的语言类似于流行的编程语言 Python。但 Python 没有这种 `for` 循环。上面的语法基于 Basic 语言。)
这个 `for` 循环意味着,"对于 1 到 `count` 之间的每个值,运行缩进的语句一次,并将变量 `i` 设置为该值。" 如果用户输入 3,你会看到
How many times? 3 (what the user types in) Are we there yet? 1 Are we there yet? 2 Are we there yet? 3
1、2、3 是每次迭代的 `i` 值。请注意,我们不再需要在每次迭代中减少 `count` 的值。计算机会在每次迭代中自动将 `i` 增加 1,直到它达到 `count`。事实上,在循环结束后,`count` 未被更改。这个循环
for i = 1 to count: print i
与这个版本本质上相同
i = 1 while i <= count: print count i = i + 1
当你想覆盖一系列数字时,`for` 循环通常比 `while` 循环更可取。它更短,更容易阅读。但是,`while` 循环更灵活,因为所有工作都由你自己完成。你可以在每次迭代中将 `i` 增加 2 以查看奇数,或者将 `i` 的值加倍以查看所有 2 的幂
print "What is the maximum?" maximum = input() i = 1 while i <= maximum: print i i = i * 2
What is the maximum? 128 (what the user types in) 1 2 4 8 16 32 64 128
你无法用简单的 `for` 循环做到这一点。顺便说一下,在 `for` 循环中,起始值和结束值(在我们的示例中为 1 和 `count`)实际上可以是任何一对数字。你可以做到
for i = 20 to 24: print i
来显示值 20、21、22、23 和 24。这里使用的是变量 `i`,但可以使用任何变量。`i` 是 `for` 循环中常用的变量;它代表 `索引`。你也可以使用在你的特定上下文中更有意义的变量名,例如
for year = 1992 to 2004: print "The year is " + year
另一种循环是 `foreach 循环`。它与 `for` 循环类似,只是变量不是简单地遍历一个数值范围,而是实际设置为一组数字中的每个元素
foreach year in [1992, 1996, 2000, 2004]: print "The " + year + " Olympic Games."
它也读起来几乎像一句英文句子:"对于集合 1992、1996、2000、2004 中的每一年,打印此语句。"(`注意:` Python 确实有这种 `for` 循环,只是使用的是 `for` 而不是 `foreach`。)
还有一些其他类型的循环,但它们通常是上述三种类型的变体。