在 Python 的模块与包体系中,__all__ 是一个看似简单却极具控制力的变量。它用于定义一个模块或包在使用 from xxx import * 时的公开接口(Public API),是实现封装、接口管理与工程化代码结构的关键工具。
Python 的导入机制向来强调“显式优于隐式”,而 __all__ 正体现了这一哲学:作者显式决定用户能看到什么、不能看到什么。
一、__all__ 的作用概述
在任何模块或者包的 __init__.py 中,只要定义了:
__all__ = ["name1", "name2", ...]那么当用户执行:
from module import *只有 __all__ 中列出的名称会被导入。
它本质上是一个导出白名单。
如果模块或包没有定义 __all__,那么:
from module import *将导入所有不以下划线 _ 开头的名称。
示例:
def func(): pass执行:
print(dir())结果包含:
func而 _y 被视为“内部名称”,不会被导入。
这也是为什么企业级项目往往认为 from ... import * 不够安全:
没定义 __all__ 时,公开接口是隐式推断的,容易产生污染与冲突。
二、__all__ 的标准写法与行为
(1)基本示例
return "hidden"用户端:
_secret() # 报错:未导入_secret 即使不以下划线开头,也不会被导入。
(2)在包的 __init__.py 中使用 __all__
位置结构:
b.py__init__.py:
__all__ = ["func_a", "func_b"]用户只需:
from mypkg import *即可获得统一后的公共接口。
(3)在多级包中的控制
层级结构:
io.py两层都可使用 __all__ 各自管理对上层的可见性,最终决定用户能访问什么。
三、__all__ 的设计动机
企业级项目通常强调 API 的稳定性与可控性,而 __all__ 能解决三个工程痛点。
(1)防止命名污染(避免 * 导入把内部逻辑暴露出去)
没有 __all__ 时,一个模块中新增任何“非下划线名称”,都会被自动公开,导致 API 不稳定。
(2)构建“面向用户的公共接口”
特别是在复杂包的 __init__.py 中,可以用 __all__ 构建统一接口层,让用户与内部结构解耦。
(3)稳固的封装机制
封装不仅是“不让别人看到”,更重要是“不让别人依赖内部结构”。
__all__ 让维护者可以明确声明 “这是对外 API,其余均为内部实现”。
四、常见使用模式
(1)显式导出函数与类
def utility(): ...(2)阻止特定名称被导入
即使不以下划线开头,也可阻止导出:
__all__ = ["api"](3)组合多个子模块的接口成为统一 API
__all__ = ["add", "sub", "format_name"]这让包即使内部结构复杂,对外接口仍保持整洁一致。
(4)动态构建 __all__
有时模块想自动暴露所有非下划线名称,但仍显式控制:
__all__ = [name for name in globals() if not name.startswith("_")]或按规则过滤:
__all__ = [name for name in globals() if callable(globals()[name])]适用于自动化驱动的大型工具包。
五、常见误区澄清
误区 1:__all__ 会影响普通 import
例如:
mathutils.func() # 无论 __all__ 是否包含 func,都可访问__all__ 仅影响 from module import *,不影响普通 import。
误区 2:定义了 __all__ 下划线函数就一定隐藏
错。
__all__ = ["_internal"]from module import * 仍会导入 _internal,因为作者将其显式加入。
误区 3:在包中使用 __all__ 会自动导入模块
不会。
__all__ = ["a", "b"]不会自动导入子模块 a.py 或 b.py,需要你显式写:
from . import a, b六、完整示例(构建可维护的公共接口)
目录:
multiply.pyadd.py:
return a + bmultiply.py:
return a * b__init__.py:
print("mypkg loaded.")用户端:
print(mul(2, 5))小结
__all__ 是 Python 模块化体系中极具工程价值的接口控制工具。它通过显式定义“允许被星号导入的名称”,使开发者能够严格管理对外 API,避免命名污染,并让大型包的结构清晰而稳定。它不影响普通导入,但能有效隔离内部实现,是构建高质量可维护库的重要机制。
熟练使用 __all__,意味着你不仅理解模块的组织方式,更真正理解了 Python 的“接口哲学”——清晰、显式、可控。
![]()
“点赞有美意,赞赏是鼓励”
特别声明:以上内容(如有图片或视频亦包括在内)为自媒体平台“网易号”用户上传并发布,本平台仅提供信息存储服务。
Notice: The content above (including the pictures and videos if any) is uploaded and posted by a user of NetEase Hao, which is a social media platform and only provides information storage services.