【问题标题】:Maintaining an uncluttered namespace维护一个整洁的命名空间
【发布时间】:2012-11-29 13:36:37
【问题描述】:

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__.py 中删除它,使用del mod_2.numpy,则该模块不再存在,因此mod_2.test2 已损坏。

我可以通过创建一个包含mod_2.py 的额外目录mod_2 来实现我想要的,但我希望尽可能保持目录结构不变。

这是我最初的问题。

编辑:我不介意做一些名字修饰来阻止一个名字踩到另一个名字。假设将mod_2.py 的相关位放入foo._mod_2

【问题讨论】:

  • del mod_1 将引发NameError 异常,您没有导入mod_1,而是导入了包含在in mod_1 中的名称。
  • 为什么mod_2.numpy存在是个问题?
  • @MartijnPieters no NameError (我假设因为 mod_1 作为包的一部分隐含地存在)。因为强迫症的卫生。

标签: python namespaces


【解决方案1】:

不想这样做,因为你发现你破坏了你的代码。

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,或者使用 @987654325 @模块。

导入只是意味着在当前模块中添加与变量相同的名称; mod_2.numpy 与运行 import numpy 后当前模块中的 sys.modules['numpy']numpy 完全相同。

【讨论】:

  • 原来如此,很有趣。尽管我认为我最初的问题仍然是合理的 - 想要将一些 mod_2.py 导入新的命名空间(我们称之为 _mod_2
  • @HenryGomersall:那就这样做吧,没有什么能阻止你这样做,对吧?
  • 除了我不知道怎么做! ;)
  • @HenryGomersall:你已经这样做了。您将名称导入顶级 __init__ 模块。您也可以对另一个模块执行相同的导入。导入只是意味着在当前模块中添加与变量相同的名称。也许不清楚您要实现的其他目标是什么?
  • 哈哈!好的,现在很明显(很容易挂断__init__.py,因为它很特别)。把它写成 3 行答案,我会给你打勾(否则我会自己做):)
猜你喜欢
  • 1970-01-01
  • 2013-04-08
  • 2012-07-06
  • 1970-01-01
  • 2012-02-07
  • 1970-01-01
  • 1970-01-01
  • 2020-06-04
  • 1970-01-01
相关资源
最近更新 更多