2012-11-29 49 views
4

tl; dr:如何在某些__init__.py中創建新的名稱空間,並將其他名稱空間的選擇位複製到其中,而不需要新目錄中的子模塊?維護整潔的名稱空間

全部問題:

比方說,我有一個對模塊的封裝,目錄結構如下:

foo/mod_1.py 
foo/mod_2.py 
foo/__init__.py 

mod_1.py如下:

import numpy 

__all__ = ['test1'] 

def test1(): 
    return numpy.zeros(10) 

mod_2.py如下:

import numpy 

def test2(): 
    return numpy.zeros(20) 

__init__.py如下:

from mod_1 import * 
import mod_2 

del mod_1 

這產生更多或更少的所需名稱空間:

In [7]: dir(foo) 
Out[7]: 
['__builtins__', 
'__doc__', 
'__file__', 
'__name__', 
'__package__', 
'__path__', 
'mod_2', 
'test1'] 

numpy現在是在foo.mod_2命名空間。如果我試圖在__init__.pydel mod_2.numpy中刪除它,那麼該模塊將不再存在,因此mod_2.test2已損壞。

我可以通過創建一個包含mod_2.py的額外目錄mod_2來達到我想要的效果,但是我希望儘可能保持目錄結構不變。

因此我的第一個問題。

編輯:我不介意做一點點名字來阻止一個名字踩在另一個名字上。假設將mod_2.py的相關位分成foo._mod_2

+1

'del mod_1'將引發'NameError'異常,您沒有導入'mod_1',您導入了包含*在*'mod_1'中的名稱。 –

+0

爲什麼存在'mod_2.numpy'這個問題? –

+0

@MartijnPieters no NameError(我認爲是因爲mod_1隱含地作爲包的一部分)。由於OCD衛生。 –

回答

3

不要想要這樣做,因爲你發現你破壞了你的代碼。

Python是一種動態語言,內省讓我們無拘無束地訪問解釋器可以訪問的幾乎所有東西。這也適用於你的模塊。

如果它讓你感覺更好,同樣的道理也適用於標準庫:

>>> import unittest 
>>> unittest.sys 
<module 'sys' (built-in)> 
>>> unittest.types 
<module 'types' from '/opt/local/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/types.pyc'> 
>>> dir(unittest) 
['FunctionTestCase', 'TestCase', 'TestLoader', 'TestProgram', 'TestResult', 'TestSuite', 'TextTestRunner', '_CmpToKey', '_TextTestResult', '_WritelnDecorator', '__all__', '__author__', '__builtins__', '__doc__', '__email__', '__file__', '__metaclass__', '__name__', '__package__', '__unittest', '__version__', '_makeLoader', '_strclass', 'defaultTestLoader', 'findTestCases', 'getTestCaseNames', 'main', 'makeSuite', 'os', 'sys', 'time', 'traceback', 'types'] 

一切一個模塊需要在它的全局命名空間可以從外面看到。 這是正常的

正如您已經發現的那樣,使用__all__來控制from modulename import *通配符導入,否則將保留模塊命名空間。

當然,如果你想爲你的軟件包的用戶提供一個乾淨的API,沒有什麼能夠阻止你將作爲API一部分的名稱導入到頂層包__init__.py或者通過使用api.py模塊。

導入只是意味着在當前模塊中添加與變量相同的名稱;在運行import numpy之後,mod_2.numpy與當前模塊中的sys.modules['numpy']numpy完全相同。

+0

所以很有趣。我的第一個問題仍然是合理的,但我想 - 想要將一些mod_2.py導入一個新的命名空間(我們稱之爲_mod_2)。 –

+0

@HenryGomersall:那麼這樣做不會阻止你這麼做,對吧? –

+0

除了我不知道怎麼回事!) –

相關問題