这是一个概念性的问题,而不是一个实际的问题,我想向伟大的互联网大众寻求反馈。
我们都知道导入的模块最终会出现在该模块的命名空间中:
# Module a:
import b
__all__ = ['f']
f = lambda: None
允许你这样做:
import a
a.b # <- Valid attribute
有时这很棒,但大多数导入都是模块提供的功能的副作用。在上面的示例中,我并不是要将b
公开为a
的来电者的有效界面。
要抵消我们可以做:
import b as _b
这标志着导入是私有的。但我无法在任何地方找到这种做法,PEP8也没有谈到使用别名来将导入标记为私有。所以我认为这不常见。但从某个角度来看,我说它在语义上更加清晰,因为它可以清理模块中暴露的位,只留下你实际意味着暴露的相关接口。使用具有自动完成功能的IDE,可以使建议的列表更加纤薄。
我的问题可归结为您是否已经看到使用该模式?它有名字吗?哪些论据会反对使用它?
我没有成功使用__all__
功能隐藏b
导入。我使用PyCharm并没有看到自动填充列表发生变化。
E.g。从我可以做的一些模块:
import a
自动填充框同时显示b
和f
。
答案 0 :(得分:2)
没有人使用该模式,并且没有命名。
这是因为正确的方法是使用__all__
变量明确标记导出的名称。 IDE会像help()
等工具一样尊重这个变量。
引用import
statement documentation:
模块定义的公共名称是通过检查模块命名空间中名为
__all__
的变量来确定的。如果已定义,则它必须是一个字符串序列,这些字符串是由该模块定义或导入的名称。__all__
中给出的名称都被视为公开名称,并且必须存在。如果未定义__all__
,则公共名称集包括在模块命名空间中找到的所有名称,这些名称不以下划线字符('_'
)开头。__all__
应包含整个公共API。它旨在避免意外导出不属于API的项目(,例如在模块中导入和使用的库模块)。
(强调我的)。
答案 1 :(得分:2)
虽然Martijn Pieters说没有人真正使用下划线隐藏模块导入,但这并不完全正确。在Python的标准库本身中可以很容易地看到这种技术的痕迹(参见related question)。我们来检查一下:
$ git clone --depth 1 git@github.com:python/cpython.git
$ cd cpython/Lib
$ find -iname '*.py' | xargs grep 'as \+_' | wc -l
183
$ find -iname '*.py' | xargs grep '^import' | wc -l
4578
因此,大约4%的进口产品以下划线为前缀 - 不是大多数,但远不是“没有人”。 numpy
和matplotlib
包中也有一些示例。
对我来说,这种导入强调是导入模块的唯一正确方法,而不会在公开场合暴露它。不幸的是,它完全破坏了代码外观,因此许多开发人员避免使用它。但它比__all__
方法有一些优势:
__all__
足以告知私人公开,因为某些公开名称可能未列在那里。总而言之,_name
和__all__
都只是简单的邪恶,但实际需要修复的东西是Python的模块系统,在{{3}的印象下设计咒语。例如,比较模块在Haskell中的行为方式。
<强> UPD:强>
看起来PEP-8已经在“simple is better than complex”部分回答了这个问题:
即使正确设置
__all__
,内部接口(包,模块,类,函数,属性或其他名称)仍应以单个前导下划线为前缀。