Python中的__all__:模块公开API设计的关键工具

在Python项目中,我们经常会看到类似这样的代码:
|
|
很多初学者会疑惑:
__all__是做什么的?- 为什么需要它?
- 和
_xxx命名有什么区别? - 大型项目为什么经常使用?
本文将从基础语法到工程实践,深入理解 Python 的__all__。
上面所列代码来自scrapy。
什么是__all__?
__all__是Python模块中的一个特殊变量,用来定义:当使用from xxx import *时,哪些成员会被导入。
例如:
|
|
其他地方:
|
|
__all__明确告诉Python,这个模块对外公开的内容只有add和VERSION。
没有__all__会发生什么?
如果没有定义__all__:
|
|
执行from math_utils import *。Python默认规则会导入所有不以下划线_开头的名字。因此add、substract和VERSION都会被导入,而_debug不会。所以很多Python项目会使用_name表示内部成员。
__all__与_xxx的区别
_xxx只是一个命名约定。表示这个东西是内部实现的,不建议外部使用。
例如:
|
|
但是Python不禁止from camera import _CameraWorker依然可以。而__all__,是真正控制from camera import *导出的列表。
__all__可以暴露内部成员吗?
可以。例如:
|
|
|
|
__all__优先级高于_规则。
为什么大型项目需要__all__
小项目可能感觉不到价值。但在大型工程中,一个模块可能包含:
|
|
如果没有管理,用户不知道哪些是稳定API,哪些只是内部实现。例如:from camera import *可能导入几十个东西。这会导致命名污染、API不稳定、重构困难等问题。而使用:
|
|
模块边界清晰。
在包中的作用
Python项目经常这样组织:
-
vision
- __init__.py
- camera.py
- calibration.py
- matcher.py
|
|
然后:
|
|
外部使用时:
|
|
而不用:
|
|
这就是典型的Facade设计。
工程实践建议
__all__看似只是一个列表,但在大型项目中,它实际上承担的是:模块 API 设计、依赖隔离、架构演进的作用。
以下是工程中使用__all__ 的核心原则:
- 明确模块边界
- 只暴露稳定 API
- 隐藏内部实现
- 减少模块耦合
- 保护未来重构空间
- 让包结构更加清晰
- 把它当作 API 设计工具,而不是语法技巧
好的 Python 工程,不只是写功能,更重要的是设计清晰的模块出口。
总结
__all__的核心思想:
明确模块边界,控制公开接口。
它不是权限系统,也不是安全机制。它更像是一份模块API清单。在简单脚本中可以不用。在大型Python工程中,建议使用。合理设计__all__可以让代码:
- 更容易维护
- 更容易扩展
- 更少依赖内部实现
推荐
相关内容
- CPython 源码剖析:Python 运行的奥秘
- BeautifulSoup库使用
- Requests库使用
- Matplotlib简明教程
- Pandas简明教程
- 用Keras搭建卷积神经网络
- Tkinter简明教程
- OpenCV简明教程
支付宝
微信