【问题标题】:Why should I use __all__ in __init__ of python package?为什么要在 python 包的 __init__ 中使用 __all__?
【发布时间】:2021-03-05 13:32:37
【问题描述】:

我已经阅读了Can someone explain __all__ in Python? 并且我知道它只影响from ... import * 语句,但我无法弄清楚一个真正的用例。当我可以简单地避免在 __init__ 命名空间中导入这些名称时,为什么还要在 __all__ (干!)中重复导出的名称?

例子:

mypackage/__init__.py

from a import A

mypackage/a.py

A = "A"
A1 = "A1"

mypackage/b.py

B = "B"    

然后在python中:

>>> from mypackage import *
>>> A
'A'
>>> 
>>> A1
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
NameError: name 'A1' is not defined
>>> b
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
NameError: name 'b' is not defined

如您所见,A 在命名空间中,但 A1b 不在。为什么我必须定义__all__ = ["A"]

【问题讨论】:

    标签: python package


    【解决方案1】:

    唯一你想在你的包的__init__.py 中定义__all__ 的时间是在用户这样做时列出你想要导出的“导出”成员的名称:

    from package import *
    

    这在6.4.1. Importing * From a Package中有记录

    注意:如果您在您的包中定义__all__,则默认行为如下(来自文档 ):

    如果__all__没有定义,语句from sound.effects import * 不会将 sound.effects 包中的所有子模块导入 当前命名空间;它只确保包 sound.effects 有 已导入(可能在 __init__.py) 然后导入包中定义的任何名称。这包括任何定义的名称(和明确的子模块 加载)由__init__.py。它还包括包的任何子模块 由先前的导入语句显式加载。考虑 这段代码:

    对此的“幼稚”解释可以是:

    如果你没有定义__all__; from package import * 将引入该包中的所有内容以及 that pacakge 的__init__.py 中导入的所有内容。

    【讨论】:

    • 看看我的例子:我没有使用__all__,但无论如何我可以在from mypackage import * 中显示或隐藏名称。那么为什么要使用它呢?
    • @Zac 你可以限制* 附带的内容。在您的示例中,它将带来一切。
    • @PeterWood:不是所有内容,而是__init__ 中导入的内容(更新的示例)
    • "如果你不定义__all__from package import * 将引入该包和所有子包中的所有内容。"不是所有东西,而是__init__中导入的东西
    • @Zac 您可能想要初始化包并且需要导入标识符才能做到这一点。但是您可能不想将它们与您的包一起导出。所以你可以使用__all__来控制它。
    猜你喜欢
    • 2021-08-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-01-26
    • 1970-01-01
    • 2020-11-06
    • 2015-07-13
    • 1970-01-01
    相关资源
    最近更新 更多