【发布时间】:2009-10-27 18:21:19
【问题描述】:
使用闭包而不是 __all__ 来限制 Python 模块公开的名称是个好主意吗?这将防止程序员意外使用错误的模块名称 (import urllib; urllib.os.getlogin()) 以及避免“from x import *”命名空间污染为__all__。
def _init_module():
global foo
import bar
def foo():
return bar.baz.operation()
class Quux(bar.baz.Splort): pass
_init_module(); del _init_module
对比同一个模块使用__all__:
__all__ = ['foo']
import bar
def foo():
return bar.baz.operation()
class Quux(bar.baz.Splort): pass
函数可以采用这种风格以避免污染模块命名空间:
def foo():
import bar
bar.baz.operation()
这对于希望帮助用户在交互式内省期间帮助用户将其 API 与包对其和其他模块 API 的使用区分开来的大型包很有帮助。另一方面,也许 IPython 应该在制表符补全期间简单区分 __all__ 中的名称,并且更多的用户应该使用允许他们在文件之间跳转以查看每个名称的定义的 IDE。
【问题讨论】:
-
为什么不在使用这个模块的代码中使用
from bar import foo?我觉得我错过了什么...... -
第二位代码不使用第一位代码。它使用
__all__定义相同的模块。 -
我同意 jdb:这有多大问题?您的 _init_module 方法很奇怪,我不明白您为什么要打扰?例如,有多少开发人员不小心使用了 urllib.os.getlogin?只需编写代码并解决实际问题。
-
我不明白你对闭包优点的解释。闭包如何“防止程序员意外使用错误的模块名称”?如果有人使用
import foo as bar,那么他们会得到名字bar,如果他们使用import foo,他们就会得到名字foo。关闭有什么不同? -
我只有在 Plone 上工作时遇到过这个问题,因为它有太多的代码,没有人熟悉它,尤其是集成商。在不知不觉中,足够多的集成商通过自省发现特定名称,如果您决定删除例如
from zope.app.intid.interfaces import IIntIds来自您的模块,那么您将破坏他们的模块。当从 IPython shell 内省 API 时,很难知道任何特定的模块级名称应该是接口还是实现。