2010-10-09 31 views
7

我只是「想」我明白了導入和模塊的工作原理,但顯然我需要更多的上學。導入如何工作。爲什麼進口模塊不能繼承其他進口模塊

下面是一個例子程序和模塊(只是somerthing我這樣做是在範圍和規模更大的測試案例):

quick.py

import gtk 
from quick_window import * 

w.show_all() 
gtk.main() 

quick_window.py

w = gtk.Window() 
w.connect('destroy', lambda w: gtk.main_quit()) 
l=gtk.Label('Hello') 
w.add(l) 

運行我得到

$ python quick.py 
Traceback (most recent call last): 
    File "quick.py", line 2, in <module> 
    from quick_window import * 
    File "/home/woodnt/Dropbox/python/weather_project/plugins/quick_window.py", line 3, in <module> 
    w = gtk.Window() 
NameError: name 'gtk' is not defined 

爲了得到它的工作,我也必須導入(呃,重新導入)GTK模塊中,像這樣:

import gtk 

w = gtk.Window() 
w.connect('destroy', lambda w: gtk.main_quit()) 
l=gtk.Label('Hello') 
w.add(l) 

我爲什麼要導入GTK不止一次?這是否意味着我在內存中有2個「gtk」?

我是否必須在模塊內導入每個模塊中的所有內容?

我知道每個模塊都有它自己的命名空間,但我認爲它也繼承了「全局變量」,包括調用程序中的導入模塊。

我一直覺得從模塊導入*就像是將代碼粘貼到該位置。還有另一種方法可以做到嗎?

非常感謝幫助。

Narnie

+0

至少因爲你不應該假設在導入模塊也導入了特定模塊的情況下編寫模塊。 – delnan 2010-10-09 17:28:09

回答

13

導入的細節變得非常複雜,但概念上它非常簡單。

當你寫:

import some_module 

這是相同的:

some_module = import_module("some_module") 

其中import_module是那種喜歡:

def import_module(modname): 
    if modname in sys.modules: 
     module = sys.modules[modname] 
    else: 
     filename = find_file_for_module(modname) 
     python_code = open(filename).read() 
     module = create_module_from_code(python_code) 
     sys.modules[modname] = module 
    return module 

兩件事需要注意的是:分配some_module是特定的:除了賦值模塊對象之外,導入語句在當前模塊中確實沒有任何作用ct到您指定的名稱。這就是爲什麼您不會自動從導入的模塊中獲取名稱,以及爲什麼它不像將導入的代碼複製到當前模塊中。

另外,在import_module僞函數中,如果名稱已經導入某處,它將位於所有模塊(sys.modules)的全局列表中,因此將被重用。該文件不會再次打開,不會再次執行,該模塊中的全局變量不會再次獲取新值,依此類推。將相同模塊導入許多地方不是浪費或額外工作,而是非常快速。

+1

「引擎蓋下」的這個高峯幫助我更好地理解正在發生的事情。謝謝。 – narnie 2010-10-09 16:28:43

+0

謝謝@Ned Batchelder,你今天幫助我。 – 2013-12-23 13:09:18

6

進口量需攜帶PY文件的內容到該模塊的命名空間 - 如果你不進口,在它的名字不能被引用。

一些更多的信息:http://effbot.org/zone/import-confusion.htm

當Python導入一個模塊,它首先 檢查模塊註冊表 (sys.modules中),看看是否該模塊 已經導入。如果是這樣, Python按原樣使用現有模塊對象 。

+0

需要特別注意的是,無論您導入模塊多少次,導入模塊中的外部代碼段只運行一次(當然,禁止卸載和重新加載)。 OP在內存中不會有2個'gtk'。後續導入的效果只是將東西帶入本地名稱空間。 – 2010-10-09 01:56:23

+0

感謝您的澄清。這似乎是很多「額外」的工作,而且這樣做有點浪費,但如果事情是這樣,那就是這樣。感謝鏈接。我剛開始閱讀,我認爲這正是我需要在Python中更好地思考的問題。 – narnie 2010-10-09 02:14:56