我在__init__.py文件中看到__all__。它做什么?
当前回答
简短的回答
__all__影响<module>import*语句。
答案很长
考虑以下示例:
foo
├── bar.py
└── __init__.py
在foo/__init__.py中:
(隐式)如果我们不定义__all__,那么from foo import*将只导入foo/__init__.py中定义的名称。(显式)如果我们定义__all__=[],那么from foo import*将不导入任何内容。(显式)如果我们定义__all__=[<name1>,…],那么from foo import*将只导入这些名称。
注意,在隐式情况下,python不会导入以_开头的名称。但是,您可以使用__all__强制导入此类名称。
您可以在此处查看Python文档。
其他回答
简短的回答
__all__影响<module>import*语句。
答案很长
考虑以下示例:
foo
├── bar.py
└── __init__.py
在foo/__init__.py中:
(隐式)如果我们不定义__all__,那么from foo import*将只导入foo/__init__.py中定义的名称。(显式)如果我们定义__all__=[],那么from foo import*将不导入任何内容。(显式)如果我们定义__all__=[<name1>,…],那么from foo import*将只导入这些名称。
注意,在隐式情况下,python不会导入以_开头的名称。但是,您可以使用__all__强制导入此类名称。
您可以在此处查看Python文档。
它是该模块的公共对象列表,由import*解释。它覆盖了隐藏以下划线开头的所有内容的默认设置。
__all__影响from foo import*的工作方式。
模块主体(但不在函数或类主体中)内的代码可以在from语句中使用星号(*):
from foo import *
*请求将foo模块的所有属性(以下划线开头的属性除外)绑定为导入模块中的全局变量。当foo有一个__all__属性时,该属性的值是由该类型的from语句绑定的名称列表。
如果foo是一个包,并且它的__init__.py定义了一个名为__all__的列表,那么当遇到from foo import*时,它将被视为应该导入的子模块名称列表。如果__all__未定义,foo import*的语句将导入包中定义的任何名称。这包括__init__.py定义的任何名称(以及显式加载的子模块)。
注意__all__不一定是列表。根据import语句的文档,如果已定义,__all__必须是由模块定义或导入的字符串序列。因此,您不妨使用元组来节省一些内存和CPU周期。如果模块定义了一个公共名称,请不要忘记逗号:
__all__ = ('some_name',)
另请参见为什么“import*”不好?
链接到,但此处未明确提及,正是使用__all__的时间。这是一个字符串列表,用于定义当在模块上使用from<module>import*时,将导出模块中的符号。
例如,foo.py中的以下代码显式导出符号bar和baz:
__all__ = ['bar', 'baz']
waz = 5
bar = 10
def baz(): return 'baz'
然后可以按如下方式导入这些符号:
from foo import *
print(bar)
print(baz)
# The following will trigger an exception, as "waz" is not exported by the module
print(waz)
如果上面的__all__被注释掉,则该代码将执行到完成,因为import*的默认行为是从给定的命名空间中导入所有不以下划线开头的符号。
参考:https://docs.python.org/tutorial/modules.html#importing-从一个包
注意:__all__仅影响from<module>import*行为。__all__中未提及的成员仍可从模块外部访问,并可通过<module>import<member>导入。
它还改变了pydoc将显示的内容:
模块1.py
a = "A"
b = "B"
c = "C"
模块2.py
__all__ = ['a', 'b']
a = "A"
b = "B"
c = "C"
$pydoc模块1
Help on module module1: NAME module1 FILE module1.py DATA a = 'A' b = 'B' c = 'C'
$pydoc模块2
Help on module module2: NAME module2 FILE module2.py DATA __all__ = ['a', 'b'] a = 'A' b = 'B'
我在我的所有模块中声明__all__,并强调内部细节,这些在使用以前从未在实时解释器会话中使用过的东西时非常有用。