使用闭包而不是__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__
的相同模块相比:
函数可以采用这种样式来避免污染模块名称空间:
def foo():
import bar
bar.baz.operation()
对于一个希望帮助用户在交互式自省期间区分其API和包对其和其他模块API的使用的大型包来说,这可能很有帮助。另一方面,也许IPython应该在制表符完成期间简单地区分__all__
中的名称,并且更多的用户应该使用一个IDE,允许他们在文件之间跳转以查看每个名称的定义。在
from x import *
的问题在于它可以隐藏NameErrors
,这使得很难追踪到微小的bug。”名称空间污染“意味着在名称空间中添加一些你不知道它来自何处的东西。在这也是你的结案方式。另外,它可能会混淆ide、outlines、pylint等。在
为模块使用“错误”的名称也不是真正的问题。无论从何处导入模块对象,它们都是相同的。如果“错误”的名字消失了(在更新之后),那就应该弄清楚原因,并激励程序员下次正确地这么做。但它不会引起虫子。在
我是一个写代码的粉丝,它绝对是头脑中最简单的。在
__all__
是Python的一个特性,它显式添加是为了解决限制模块显示哪些名称的问题。当你使用它时,人们会立刻明白你在用它做什么。在你的收尾技巧很不规范,如果我遇到了,我不会马上理解的。您需要输入一个长注释来解释它,然后需要再输入一个长注释来解释为什么要这样做,而不是使用
__all__
。在编辑:既然我对这个问题有了更好的理解,这里有一个替代答案。在
在Python中,在模块中使用下划线作为私有名称前缀是一种很好的做法。如果您这样做
from the_module_name import *
,您将得到所有不以下划线开头的名称。因此,与其说闭包技巧,我更希望看到初始下划线习惯用法的正确使用。在请注意,如果使用初始下划线名称,甚至不需要使用
__all__
。在好吧,我开始对这个问题有点了解了。关闭确实允许隐藏私人物品。下面是一个简单的例子。在
没有关闭:
关闭后:
^{pr2}$使用示例:
这实际上是令人不安的微妙之处。在第一种情况下,函数},
foo()
只是引用了名称_bar()
,如果要从名称空间中删除{foo()
将停止工作。foo()
每次运行时都会查找_bar()
。在相反,
foo()
的闭包版本在名称空间中没有_bar()
的情况下工作。我甚至不确定它是怎么工作的。。。它是保存对为_bar()
创建的函数对象的引用,还是对仍然存在的名称空间的引用,以便它可以查找名称_bar()
并找到它?在相关问题 更多 >
编程相关推荐