Python __all__似乎可以多种方式工作

问题描述 投票:1回答:1

import语句(link)的Python文档包含以下内容:

由模块定义的公共名称是通过检查模块名称空间中名为__all__的变量来确定的;如果已定义,则它必须是由该模块定义或导入的名称的字符串序列。

模块(link)的Python文档包含看似矛盾的声明:

如果程序包的__init__.py代码定义了名为__all__的列表,则将其视为遇到from package import *时应导入的模块名称的列表。

然后给出一个示例,其中__init__.py文件不导入任何内容,仅将__all__定义为该程序包中某些模块的名称。

我已经测试了使用__all__的两种方法,并且似乎都可行;实际上,一个人可以在同一__all__值内进行混合和匹配。


例如,考虑目录结构

foopkg/
  __init__.py
  foo.py

__init__.py包含的位置

# Note no imports

def bar():
    print("BAR")

__all__ = ["bar", "foo"]

NOTE:我知道不应该在__init__.py文件中定义函数。我只是为了说明相同的__all__可以导出当前名称空间中确实存在的名称和不存在的名称。

以下代码运行,似乎自动导入了foo模块:

>>> from foopkg import *
>>> dir()
[..., 'bar', 'foo']

为什么__all__属性具有这种奇怪的双重行为?

文档似乎对于应该如何使用还不清楚,只在我链接的每个地方都提到了它的两个方面之一。我知道总体目的是显式设置通配符导入所导入的名称,但被其他看似自动导入的行为所迷惑。这只是一个魔术快捷方式,它也避免了必须写出导入文件吗?

python
1个回答
0
投票

您可以将foopkg(文件夹)想象为一个foopkg.py模块

在您的示例中,您可以这样做吗?:

from foopkg import foo

因此__all__中的__init__.py的行为类似于__all__中的foopkg.py。该功能是将您from foopkg import *时可以导入的内容列入白名单。(希望这个比喻不会引起混淆)

© www.soinside.com 2019 - 2024. All rights reserved.