meishaoming / blog

MIT License
1 stars 2 forks source link

python 中的 __all__ #92

Open meishaoming opened 4 years ago

meishaoming commented 4 years ago

__all__ 是一个列表,常见于模块文件头部和包的init.py 头部。

模块中的 __all__

比如 queue.py 中就有:

__all__ = ['Empty', 'Full', 'Queue', 'PriorityQueue', 'LifoQueue', 'SimpleQueue']

from module import * 时起作用。

如果模块中有 __all__ 列表,则只导入 __all__ 列表中指定的名称。这些名称可以是本源文件中定义的变量、函数、类,也可以是从别处导入的名称。

如果模块中没有 __all__ ,则会导入所有的不以下划线打头的名称。

做个测试:

__all__ = [ 'hello1' ]

def hello():
    print('hello')

def hello1():
    print('hello1')

def __hello__():
    print("__hello__")
>>> from test import *
>>> globals()
{'__name__': '__main__', '__doc__': None, '__package__': None, '__loader__': <class '_frozen_importlib.BuiltinImporter'>, '__spec__': None, '__annotations__': {}, '__builtins__': <module 'builtins' (built-in)>, 'hello1': <function hello1 at 0x104330f28>}
>>>

可以看到只导入了 hello1。hello 和 __hello__ 都没有导入

如果把文件中的 __all__ 一行注释掉,重新导入的结果:

>>> from test import *
>>> globals()
{'__name__': '__main__', '__doc__': None, '__package__': None, '__loader__': <class '_frozen_importlib.BuiltinImporter'>, '__spec__': None, '__annotations__': {}, '__builtins__': <module 'builtins' (built-in)>, 'hello': <function hello at 0x10fcdaea0>, 'hello1': <function hello1 at 0x10fcdaf28>}
>>> 

这次导入了 hello 和 hello1,但是没有 __helo__

包中的 __all__

是同样的道理。引入一下文档里的原话:

如果一个包的 init.py 代码定义了一个名为 all 的列表,它会被视为在遇到 from package import * 时应该导入的模块名列表。

如果没有定义 allfrom sound.effects import * 语句 不 会从包 sound.effects 中导入所有子模块到当前命名空间;它只确保导入了包 sound.effects (可能运行任何在 init.py 中的初始化代码),然后导入包中定义的任何名称。这包括 init.py 定义的任何名称(以及显式加载的子模块)。它还包括由之前的 import 语句显式加载的包的任何子模块。