唠唠python(5) -- 打包操作

这篇文章依然是承接自上一篇文章,来讲一讲上一章遗留下来的问题。

上一章我们讲到int(raw_input('Tell me the quantity: '))是让计算机帮我们从用户那里获取一个数字,现在我们来看看它是如何做的。

洗衣机的智慧

对,我们先来谈一谈洗衣机。

我现在住的这个地方有点小,担心买了洗衣机更显局促,所以一直没买。但这不妨碍我们谈洗衣机的智慧。

如果现在还没有出现洗衣机这么个东西,设想我们渴望有一个机器,它可以帮我们(1)自动加水,(2)清洗衣物,(3)自动甩干,(4)自动烘干。

这么一大批动作,当然每个动作分别需要一个机器也是可以的,但是每一个动作人为介入,势必会降低我们的效率。怎么办呢?

哈哈,其实办法我们已经知道了,但还是要假装吃惊一下。啊?居然还有机器可以集成上面说到的全部功能,而且只需要在执行第一步前按一个按钮,接下来的四步自动依次完成,帮我们屏蔽了之前的细节。

这样的例子有很多,人类的智慧大大促进了人们生活水平的提高。

洗衣机智慧在计算机语言中的妙用

刚刚我们谈了洗衣机的智慧,我们再进一步来谈一下,对我们来说,它到底意味着什么。

我们知道,光洗衣服这件小事,就涉及了非常多个工序。什么倒洗衣粉、搓洗衣服、拧干、晾晒,等了个等。像我们这种追求(zhi)生活(nan)品质(ai)的人,怎么能忍受得了这么变态的工序。

福音来了,现在你眼前的这个工具,只需要把衣物放进去,按下开关。二小时后,将衣物取出放进衣柜就可以万事大吉了。

为什么这么神奇,因为洗衣机帮我们把洗衣服的细节给屏蔽掉了。它把必须由我们来做的事(打开开关)暴露给我们(看得见的开关按钮),我们只需要打开开关,二小时后,它就会把结果(衣服洗完)给我们。

计算机语言也存在着类似的思想。

我们再拿之前提到的表格处理的例子,我们希望把表格中每个数字,按照某种规则处理完后写到其下面的表格,然后将处理后的表格保存到一个新文件。

假设我们有一台表格洗衣机,来达到上面的效果。我们假设这台表格洗衣机是洗衣机厂家生产的。我们不管厂家怎么制作出来的,也不管它怎么个洗法,我们的想法是,只要给这台表格洗衣机一个实际的数据表格(相当于洗衣机的开关)就可以了。它会把处理完后的表格给我们。

表格洗衣机仍然有点抽象,但是实际上,我们在前面已经看过两个例子了。一个是raw_input(),一个是int()

raw_input()int()

现在,我们可以来讲讲之前遇到的int(raw_input('Tell me the quantity: '))了。

这一坨长长的东西,可以等价到下面两句:

1
2
quantity_str = raw_input('Tell me the quantity: ')
quantity = int(quantity_str)

我们对洗衣机说:“帮我洗一件衣服”。然后塞给它一件衣服,打开开关,它就轰隆隆地开动了。

当计算机读到quantity_str = raw_input('Tell me the quantity: ')时,它跟用户说:“Tell me the quantity: ”,并将用户输入的文字写到quantity_str

quantity_str又是啥?我们可以把它想象成一个箱子,我们把计算机读到的用户输入的文字放到这个箱子里。

注意,这条语句是从右往左读的:“计算机显示Tell me the quantity,并把用户输入的文字放到quantity_str这个箱子里”。

现在我们知道了,raw_input()就是要计算机帮我们获得一段文字。具体怎么获得,我们不管,你(计算机)自己去想。

int()也是一样的东西,它的功能是将某段文字(如"1234")转换成一个整数。int(quantity_str)即,将我们quantity_str箱子里的文字转换成一个整数,并放到一个名为quantity的箱子。

为了更直观地感觉一下,我们来自己做一台”洗衣机”。

更好的规则计算过程

之前的例子,我们写了一段代码来实现通过规则计算结果:print (int(raw_input("Tell me the quantity: ")) + (10000 - 1)) / 10000 * 10000

这一行代码有几个问题:

  1. 首先,这一句非常长,而且里面有n个(),就算我们自己,也要用手一个括弧一个括弧地匹配。
  2. 其次,里面可能有多个中间结果,但我们没法查看中间结果的值。
  3. 再次,这段代码的自述性不好。也就是说,它不能表达自己在做什么。

我们根据这三点,再利用前面提到的技术,来重新组织一下我们的语言:

1
2
3
4
5
quantity_str = raw_input("Tell me the quantity: ")
quantity = int(quantity_str)
real_quantity = (quantity + (10000 - 1)) / 10000 * 10000

print real_quantity

看上去代码量更多了,真的值得吗?

审视一下我们上面提到的三个问题,新的代码每行不再有大量的括弧,我们可以在第二行后插入print quantity来查看quantity的内容,而且我们很清晰地看到了我们要计算机做的每一步。作为一个简单的脚本,新的代码并没有什么吸引力。但当我们考虑到我们要把它做成一个完整的系统,至少在最后的系统面前,它是值得的。

考虑当我们的规则非常复杂时,我们就会有一个更好的选择,即上面所谈的洗衣机的智慧:

1
2
3
4
5
6
7
8
def compute_real_quantity(quantity):
return (quantity + (10000 - 1)) / 10000 * 10000

quantity_str = raw_input("Tell me the quantity: ")
quantity = int(quantity_str)
real_quantity = compute_real_quantity(quantity)

print real_quantity

哇噻,更长了,哈哈。

我们在这里,定义了一个类似raw_input()的功能,叫做compute_real_quantity()。定义方式就像看到的一样简单。我们再来定义一个加法功能说明,如下:

1
2
3
4
5
def 功能名称(需要输入哪些变量):
return 结果

def add(m, n):
return m + n

这里有一个好处,如果compute_real_quantity()是别人写的,我们就不需要知道规则的细节了。假如这个规则是你来写,我只需要把我的待采购的数量给你,你帮我计算一下实际需要的数量就好了。具体细节,我不关心。

屏蔽细节让生活更轻松

我们之前说游戏手柄的输入也非常简单,原因就在于这方面的专家已经帮我们屏蔽了细节。获取手柄的输入,跟获取raw_input()的输入大同小异。

类似的,从一个表格文件中获取输入跟raw_input()差别不大。我们会使用这一篇文章中讲到的技术及之后的少量新技术,来从表格文件中读取表格数据,处理完后,使用类似print的功能,将处理结果输出到新文件(而不是神秘的黑色窗口)。

明天你是否会想起?

不止明天,我哪一天都不想起。睡觉。