2012-11-29 24 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

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

相关问题