程序员入伙书——程序在干什么?
- 2012年12月13日
- 发布在 infotech . math . on my mind
- 留下评论
程序员是写程序的,程序是干什么的?
我的独门总结:形形色色的程序,大到组成整个操作系统或者办公软件,小到打印一个九九乘法表,它们都有三个共同的功能块:
- 计算
- 流程控制
- 输入输出
计算,不但是数学运算,也包括对语言文字信息的分析,判断异同、比较大小,都属于“计算”的范畴。如果没有计算,如果所有的数据、信息都不需要处理,我们要计算机做什么?当打字机使么?
流程控制,包括条件判断、循环、跳转。通过使用流程控制,我们可以写很短的程序,让计算机重重复复地执行成千上万的步骤,并且花样繁多。计算机虽然不会思考,但它们做明确具体的事情时还是比人速度快、而且重复性好。你让计算机做两个数相除,做一亿次的结果都是一样的,且它也不喊累。可让人来做的话,首先就是慢,也可能做错,做十次会不耐烦,做五百次会精神崩溃。小时候被老师罚抄作业十遍的同学,请自行默默回忆童年时的阴影。
输入:键盘、鼠标指令,从网络上接收服务请求,或者从硬盘读个图片……把外部设备上的电信号吸纳进计算机的过程,都算是输入。输出:在屏幕上显示一张图片、一些文字,往U盘上拷东西,播放音乐或视频……把计算机心里想明白的事情说出来的过程,这些都是输出。如果程序没有输入,那么它每次的运算都是从已知的、固定的条件开始,结果会单调得让人厌烦。学编程的时候,看到一群老年大专生用BASIC语言打印熊猫,以为自己在编程,心里的怜悯油然而生。如果程序没有输出,计算机有电没电的区别就不太大了,当然,冬天屋里冷的时候,多开个电器,确实可以更暖和一些。
可以说,所有的程序做的事情不外乎这三个概念。你打开网络浏览器,IE也好,FireFox也罢,你输入一个网址,按回车键,它就向网络端口上输出一个请求,向那个网址要网页,要来的网页从网络端口输入进来,浏览器反复判断每个传进来的数据流,看它们是图片还是一般文字,如果是图片,还需要做些解码工作,计算摆放它们的位置,显示在窗口上。在这个回合里,计算、流程控制、输入输出都是齐全的。除了这三样,确实也没有其它的操作了。
说了这么多,我来演示三个例子吧。
第一个例子,是算从1加到100的总和,传说高斯用很聪明的办法搞定了这道题,我们来看看很笨很死脑筋、却擅长做高速计算的计算机是怎么做的。打开Python的窗口(说啥呢?),输入(虽然可以拷贝粘贴,但我更希望你亲自敲一遍):
total = 0 for i in range(1, 101): total = total + i # 请在这里多敲一两次回车(Enter)键,以使Python显示>>>提示符 print(total)
打字时请注意,Python对每行的缩进要求很严格,因为它认为这是表达程序结构的一部分,所以一定要按照这个例子里来敲。敲完最后一行“print(total)”,如果你看到了5050,就知道自己做对了。
讲解一下:这个程序的逻辑很简单,就是从1到100一路累加下去。你可以想象一个空箱子,第一次我们往里头放1个桃,第二次放2个桃,第三次放3个桃,一直这样放下去,最后一次放100个桃。然后我们停下来,数一下箱子里有多少个桃子。
这段程序里,第一行的“total = 0”就是“准备一个空箱子”,第二行的“for i in range(1, 101):”意思是:把以下缩进内容循环执行100次,每次循环时,把1、2、3、……100轮番放到i里去。range括号里的101是个结束量,本身不计入循环。
第三行相对于第二行缩进,表示它是被循环执行的一句。做惯数学题的同学们一定会对这句话大惑不解,既然total = total + i,那么等式两边的total互相抵消,i一定等于0了。在程序员的世界里,这句话却是这么理解的:等号不是“相等”,而是“把等号右边的计算结果放到左边的变量里来”的意思。所以这句话就是:把total和i相加,计算结果还放回到total里来。
敲完这行后打回车键,Python不确定你是不是还有其它的东西要交给上头的for语句循环,就把光标停在缩进几格的位置等着,因为我们这个程序很简单,只有一个累加操作,所以可以再敲一个回车,意思是我没有其它的语句要在for循环里做了。Python就把光标停在顶头一格,然后显示出>>>提示符来,我们再输入print(total)来显示total的值(箱子里现在有多少个苹果),程序到这里就做完了,结果和我们预想的一样:5050。
第二个例子,是打印九九乘法表,请仔细输入:
for i in range(1, 10): for j in range(1, i + 1): print("%3d" % (i * j), end='') print('')
再次提醒:打字时请注意,Python对每行的缩进要求很严格,因为它认为这是表达程序结构的一部分,所以一定要按照这个例子里来敲,每打一个Tab(制表符)缩进一层。
打完最后一行时,Python会在那里默默地等着你,看你还有没有别的话说。你只要再打一个回车,它就会明白你已经没有什么要补充的了,于是它开始运行这段程序,输出以下结果:
1 2 4 3 6 9 4 8 12 16 5 10 15 20 25 6 12 18 24 30 36 7 14 21 28 35 42 49 8 16 24 32 40 48 56 64 9 18 27 36 45 54 63 72 81
现在讲解一下。
这个程序的第一行“for in in range(1, 10):”意思是说:把以下缩进的内容循环9次,循环第一次时,让变量i等于1,循环第二次时,让变量i等于2,……range身后的括号里的第二个数字是10,这样可以把i从1循环到9,而到10的时候循环就停了。
第二行“for j in range(1, i + 1):”说:把以下缩进的内容循环若干次。若干次是多少次?得看i等于多少。如果i等于4,那就是循环4次。注意在range里,我写的是i + 1,之所以加上1,是因为i + 1本身不计入循环,这样可以让j刚好从1循环到i。
第三行“print(“%3d” % (i * j), end=”)”比第二行更缩进一层,所以第二行所说的循环,就是循环这一句。这一句的意思是说:计算i乘以j(i * j,乘号在Python里表达为星号),计算结果向右对齐、连空格带结果共占三个格子(所谓”%3d”)打印出来(print),打印完本结果之后,不要着急换行(end = ”)。如果不写这个end = ”,print就会自作主张地在i乘以j的计算结果后面跟一个换行。
第四行“print(”)”的意思是说:现在可以换行了。打印一个空字符(两个单引号之间什么都没有”),默认跟一个换行。
我们来手工跑一下这个程序:
进入第一层循环。
i = 1。
进入第二层循环。
j = 1。
计算i * j,得到1。
把1打印到屏幕上,不要换行。
因为j现在已经等于i了,第二层循环做完了,现在执行第二层循环后面这句。
打印一个空字符,默认再打一个换行。
现在屏幕上显示
1
i现在还小于10,第一层循环需要继续执行下去。
i = 2。
进入第二层循环。
j = 1。
计算i * j,得到2。
把2打印到屏幕上,不要换行。
现在屏幕上显示
1 2
j现在还小于i,第二层循环继续。
j = 2。
计算i * j,得到4。
把4打印到屏幕上,不要换行。
因为j现在已经等于i了,第二层循环做完了,现在执行第二层循环后面这句。
打印一个空字符,默认再打一个换行。
现在屏幕上显示
1 2 4
i现在还小于10,第一层循环需要继续执行下去。
i = 3。
进入第二层循环。
j = 1。
计算i * j,得到3。
:
:
:
前两个例子里有计算:total加i或者i乘以j,隐藏在range里头的i和j的递增都是。有流程控制:用for引导的循环就是。没有输入,因为我们很确定被计算的对象:从1累加到100,是九九乘法表而不是三三乘法表。有输出,5050和九九乘法表被打印在屏幕上。
再举第三个例子,这个例子里有运算、流程控制、和观众互动的输入输出。它的功能是,你随意给它一个数字,它通过猜测的方法“计算”出这个数字的平方根。
因为这里有需要输入的环节,我担心你敲完代表“请输入一个数字”这句话,Python就会误认为紧接着的下一行程序是你的输入。所以,这里我们换一种方法来玩。请点击Python窗口菜单的File,然后选New Window,会弹出一个不带提示符的空白窗口。在这个窗口里,输入以下程序段(我们也常常称之为“代码”,是英文code的意译):
print('Please input a number: ', end = '') n = abs(float(input())) high = max(1, n) low = 0 while True: result = (high + low) / 2 if abs(result * result - n) < n * 1E-8: break if result * result > n: high = result else: low = result print('Square root of %g is %g' % (n, result))
输入完毕后,点菜单File选Save(或者直接按Ctrl-S),把这个程序起个名字存到硬盘上(名字随意,我推荐sqrt.py,意思是square root . python)。
现在点菜单Run选Run Module(或者直接按F5键),会应声跳出Python Shell窗口,显示:
>>> ======================= RESTART ======================= >>> Please input a number:
恭请你出题。随意输入一个数字,敲回车,看看结果吧:
>>> ======================= RESTART ======================= >>> Please input a number: 3 Square root of 3 is 1.73205
对于这个例子,我这次不做讲解了,请读者自己悟一下,为什么通过做四则运算就可以求平方根呢? 🙂
在Python里,不是常量的,就是变量。3.14、2、1000、”hello, world”这种数或字符串,已知的、不会改变的,叫做常量。2只能等于2,不能等于其他的东西。而内容可以改变的这些“名字”:result、n什么的,就都是变量。
话说它是怎么知道n和result是变量的?
看来只要后面有(x,y),前面的%g就知道要管哪个了。