Python - 我应该用下划线为导入别名吗?

Jon*_*sen 5 python

这是一个概念性问题,而不是一个实际问题,我想向广大互联网群众寻求反馈。

我们都知道导入的模块最终位于该模块的命名空间中:

# Module a:
import b
__all__ = ['f']
f = lambda: None
Run Code Online (Sandbox Code Playgroud)

这允许你这样做:

import a
a.b  # <- Valid attribute
Run Code Online (Sandbox Code Playgroud)

有时这很好,但大多数导入都是模块提供的功能的副作用。在上面的示例中,我并不是b要向a.

为了抵消这个问题,我们可以这样做:

import b as _b
Run Code Online (Sandbox Code Playgroud)

这将导入标记为私有。但我找不到任何地方描述的这种做法,PEP8 也没有讨论使用别名将导入标记为私有。所以我认为这不是常见的做法。但从某个角度来看,我想说它在语义上肯定更清晰,因为它清理了模块的暴露部分,只留下您实际想要暴露的相关接口。使用具有自动完成功能的 IDE 可以使建议列表变得更加精简。

我的问题归结为您是否见过这种模式的使用?它有名字吗?什么论据会反对使用它?

我没有成功使用__all__隐藏b导入的功能。我正在使用 PyCharm,但没有看到自动完成列表发生变化。

例如,从某个模块我可以执行以下操作:

import a
Run Code Online (Sandbox Code Playgroud)

自动完成框显示bf

fir*_*iku 6

虽然 Martijn Pieters 说没有人真正使用下划线隐藏模块导入,但这并不完全正确。这种技术的痕迹可以在Python的标准库本身中很容易地看到(参见相关问题)。让我们检查一下:

\n\n
$ git clone --depth 1 git@github.com:python/cpython.git\n$ cd cpython/Lib\n$ find -iname \'*.py\' | xargs grep \'as \\+_\' | wc -l\n183\n$ find -iname \'*.py\' | xargs grep \'^import\' | wc -l\n4578\n
Run Code Online (Sandbox Code Playgroud)\n\n

因此,大约 4% 的导入都是以下划线前缀的 \xe2\x80\x94 ,虽然不是大多数,但还远远低于 \xe2\x80\x9cno one\xe2\x80\x9d 。numpy和包中也有一些示例matplotlib

\n\n

对我来说,这种导入下划线是导入模块而不将其公开的唯一正确方法。不幸的是,它完全破坏了代码的外观,因此许多开发人员避免使用它。但与该方法相比,它有一些优点__all__

\n\n
    \n
  • 图书馆用户只需查看名称即可决定名称是否私有,而无需查阅文档。仅查看并__all__不足以区分私人和公共名称,因为某些公共名称可能未列出
  • \n
  • 无需维护不利于重构的代码实体名称列表。
  • \n
\n\n

总而言之, 和_name都是__all__纯粹的邪恶,但真正需要修复的是Python的模块系统,它是在\xe2\x80\x9csimple优于complex\xe2\x80\x9d口头禅的印象下设计的。例如,与 Haskell 中模块的行为方式进行比较。

\n\n

UPD:
\n看起来 PEP-8 已经在其\xe2\x80\x9cPublic 和内部接口\xe2\x80\x9d部分回答了这个问题:

\n\n
\n

即使__all__设置正确,内部接口(包、模块、类、函数、属性或其他名称)仍应以单个前导下划线为前缀。

\n
\n