首页 » 与孩子一起学编程 » 与孩子一起学编程全文在线阅读

《与孩子一起学编程》15.6 命名空间

关灯直达底部

Carter 提到的内容与命名空间(namespace)概念有关。这个话题有点复杂,不过确实需要知道,所以现在就来讨论这个概念。

什么是命名空间

假设在你们学校,你在 Morton 老师的班里,班里有个学生名叫 Shawn。现在 Wheeler 老师教的那个班也有一个名叫 Shawn 的学生。如果你在自己的班里说“Shawn 有一个新书包”时,你们班的所有人都会知道(或者至少他们会认为),你指的是你们班的 Shawn。如果你想说另外那个班的 Shawn 就会说“Wheeler 老师班里的 Shawn”或者“另外那个 Shawn”,或者其他类似的说法。

你们班里只有一个 Shawn,所以你说 Shawn 时,同班的同学就会知道你说的是哪个人。换种说法来讲,在你们班的这个空间里,只有一个名字 Shawn。你们班就是你的命名空间,在这个命名空间里只有一个 Shawn,所以不会有混淆。

现在,如果校长必须通过学校的广播系统把 Shawn 叫到办公室,她不会说“请 Shawn 到办公室来一趟”。如果她这样做,两个 Shawn 都会出现在他的办公室。对于使用广播系统的校长来说,命名空间是整个学校。这说明,学校的每一个人都会听到这个名字,而不只是一个班的同学。所以她必须更明确地指出她指的是哪一个Shawn。她必须这样说:“请 Morton 老师班里的 Shawn 到办公室来一趟。”

校长还可以用另一种方法找 Shawn,就是走到你们班门口说:“Shawn,请跟我来。”这里只有一个 Shawn 听到,所以校长能找到真正要找的那个 Shawn。在这种情况下,命名空间就只是一个教室,而不是整个学校。

一般来讲,程序员把较小的命名空间(比如你的教室)称作局部命名空间,而较大的命名空间(如整个学校)称为全局命名空间。

导入命名空间

下面假设你们学校(John Young 学校)根本没有一个名叫 Fred 的人。如果校长通过广播系统想找 Fred,她肯定找不到这个人。现在假设与你们学校同在一条街上的另一个学校(Stephen Leacock 学校)正在进行部分校舍维修,这个学校把一个班级临时搬到你们学校的活动房里上课。在这个班里,恰好有一个学生名叫 Fred。不过这个活动房还没有连上广播系统。如果校长找 Fred,肯定还是找不到。但是,如果她把这个新的活动房连入广播系统,然后再找 Fred,就会找到 Stephen Leacock 学校的 Fred。

连接另一个学校的活动房屋,这在 Python 中就像导入一个模块。导入了模块,就可以访问这个模块中的所有名字,包括所有变量、函数以及对象。

导入模块的含义与导入一个命名空间是一样的。导入模块时,就导入了命名空间。

导入命名空间(模块)有两种方法。可以这样做:

import StephenLeacock

如果这样做,StephenLeacock 仍然是一个单独的命名空间。你可以访问这个命名空间,但是在使用之前必须明确地指定想要哪一个命名空间。所以校长必须这样做:

call_to_office(StephenLeacock.Fred)

如果校长想找到 Fred,除了名字(Fred)外,她还必须给出命名空间(Stephen Leacock)。在前面的温度转换程序中就是这样做的。

为了让这个程序正常工作,我们写了这样一行代码:

fahrenheit = my_module.c_to_f(celsius)

这里指定了命名空间(my_module)以及函数名(c_to_f)。

导入命名空间的另一种方法是:

from StephenLeacock import Fred

如果校长这样做,会把 StephenLeacock 的名字 Fred 包含到她的命名空间中,现在就可以这样找到 Fred:

call_to_office(Fred)

因为 Fred 现在就在校长的命名空间中,所以她不必再去 StephenLeacock 命名空间找 Fred

在这个例子中,校长只是从 StephenLeacock 把名字 Fred 导入她的局部命名空间中。如果她想导入所有人,可以这样做:

from StephenLeacock import *

在这里,星号(*)表示全部。不过她必须当心,如果 Stephen Leacock 学校与 John Young 学校有同名的学生,就会出现混乱了。

太难了

到目前为止,你可能对命名空间的概念还是不太清楚。不用担心!通过完成后面 几章的例子,你会越来越明白。后面需要导入模块时,我都会清楚地解释要做什么。