理解 Python 中的 __all__

在 GitHub 上寻找开源项目的时候偶然看到 osxphotos 里面有个 issue 是在 Python 文件中显式的定义 __all__。里面还附了份链接解释为什么需要 __all__。在这里东施效颦的用中文解释一下。

TL;DR

__all__ 定义的字符串列表规定了 from module import * 会导入该文件中的哪些类,函数,变量。不在 __all__ 中的类,函数,变量不会被导入。

__all__ 有两个目的:

  • 标明该模块想要暴漏哪些 API (类,函数,变量)
  • 当使用 from module import * 导入时,只将想要暴漏的 API 导入

举个例子,这里我们定义一个模块在 “my_module.py” 文件中

1
2
3
4
5
6
7
8
9
10
11
# my_module.py
__all__ = ["Foo", "bar"]

class Foo():
pass

def bar():
pass

def baz():
pass

当我们在另一个文件 “main.py” 中运行以下代码

1
2
3
4
5
6
#main.py
from my_module import *

foo = Foo()
bar_return = bar()
baz_return = baz() # 报错,无法找到函数 baz

我们会发现函数 baz 并没有被导入。

在写代码的时候, import * 这个语法通常并不鼓励使用。增加 __all__可以避免在使用这个语法时不必要的导入,既可以减少错误又可以提高性能。

最后附上我自己写的工具,它可以自动的为没有 __all__ 的Python文件创建一个 __all__ 并且加入文件中定义的类与函数,同时自动忽略以下划线开始的私有函数或类。

https://github.com/xwu64/python-auto-all

Recommended Posts