讀古今文學網 > 父與子的編程之旅:與小卡特一起學Python > 15.6 命名空間 >

15.6 命名空間

卡特提到的內容與命名空間(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 導入

導入命名空間的另一種方法是:

from StephenLeacock import Fred  

如果校長這樣做,會把 StephenLeacock 的名字 Fred 包含到她的命名空間中,現在就可以這樣找到 Fred:

call_to_office(Fred)  

因為 Fred 現在就在校長的命名空間中,所以她不必再去 StephenLeacock 命名空間找 Fred

在這個例子中,校長只是從 StephenLeacock 把名字 Fred 導入她的局部命名空間中。如果她想導入所有人,可以這樣做:

from StephenLeacock import *  

在這裡,星號(*)表示全部。不過她必須當心,如果 Stephen Leacock 學校與 John Young 學校有同名的學生,就會出現混亂了。

太難了

到目前為止,你可能對命名空間的概念還是不太清楚。不用擔心!通過完成後面幾章的例子,你會越來越明白。後面需要導入模塊時,我都會清楚地解釋要做什麼。