Python中__all__用法及常见误区详解

 更新时间:2025年12月29日 10:17:26   作者:MediaTea  
__all__属性是Python中用来控制模块导入行为的关键工具,它可以帮助你保持代码的整洁和封装性,防止意外地暴露内部实现细节,这篇文章主要介绍了Python中__all__用法及常见误区的相关资料,需要的朋友可以参考下

前言

在 Python 的模块与包体系中,__all__ 是一个看似简单却极具控制力的变量。它用于定义一个模块或包在使用 from xxx import * 时的公开接口(Public API),是实现封装、接口管理与工程化代码结构的关键工具。

Python 的导入机制向来强调“显式优于隐式”,而 __all__ 正体现了这一哲学:作者显式决定用户能看到什么、不能看到什么。

一、__all__ 的作用概述

在任何模块或者包的 __init__.py 中,只要定义了:

__all__ = ["name1", "name2", ...]

那么当用户执行:

from module import *

只有 __all__ 中列出的名称会被导入。

它本质上是一个导出白名单。

如果模块或包没有定义 __all__,那么:

from module import *

将导入所有不以下划线 _ 开头的名称。

示例:

# module.pyx = 1_y = 2def func(): pass

执行:

from module import *print(dir())

结果包含:

xfunc

而 _y 被视为“内部名称”,不会被导入。

这也是为什么企业级项目往往认为 from ... import * 不够安全:

没定义 __all__ 时,公开接口是隐式推断的,容易产生污染与冲突。

二、__all__ 的标准写法与行为

(1)基本示例

# mathutils.py__all__ = ["add", "mul"]
def add(a, b):    return a + b
def mul(a, b):    return a * b
def _secret():    return "hidden"

用户端:

from mathutils import *
print(add(1, 2))print(mul(2, 3))_secret()   # 报错:未导入

_secret 即使不以下划线开头,也不会被导入。

(2)在包的 __init__.py 中使用 __all__

位置结构:

mypkg/    __init__.py    a.py    b.py

__init__.py:

from .a import func_afrom .b import func_b
__all__ = ["func_a", "func_b"]

用户只需:

from mypkg import *

即可获得统一后的公共接口。

(3)在多级包中的控制

层级结构:

mypkg/    __init__.py    utils/        __init__.py        io.py

两层都可使用 __all__ 各自管理对上层的可见性,最终决定用户能访问什么。

三、__all__ 的设计动机

企业级项目通常强调 API 的稳定性与可控性,而 __all__ 能解决三个工程痛点。

(1)防止命名污染(避免 * 导入把内部逻辑暴露出去)

没有 __all__ 时,一个模块中新增任何“非下划线名称”,都会被自动公开,导致 API 不稳定。

(2)构建“面向用户的公共接口”

特别是在复杂包的 __init__.py 中,可以用 __all__ 构建统一接口层,让用户与内部结构解耦。

(3)稳固的封装机制

封装不仅是“不让别人看到”,更重要是“不让别人依赖内部结构”。

__all__ 让维护者可以明确声明 “这是对外 API,其余均为内部实现”。

四、常见使用模式

(1)显式导出函数与类

__all__ = ["A", "B", "utility"]
class A: ...class B: ...def utility(): ...

(2)阻止特定名称被导入

即使不以下划线开头,也可阻止导出:

def internal_logic():    ...
__all__ = ["api"]

(3)组合多个子模块的接口成为统一 API

# __init__.pyfrom .math import add, subfrom .string import format_name
__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

例如:

import mathutilsmathutils.func()  # 无论 __all__ 是否包含 func,都可访问

说明:

__all__ 仅影响 from module import *,不影响普通 import。

误区 2:定义了 __all__ 下划线函数就一定隐藏

错。

__all__ = ["_internal"]

from module import * 仍会导入 _internal,因为作者将其显式加入。

误区 3:在包中使用 __all__ 会自动导入模块

不会。

# __init__.py__all__ = ["a", "b"]

不会自动导入子模块 a.py 或 b.py,需要你显式写:

from . import a, b

六、完整示例(构建可维护的公共接口)

目录:

mypkg/    __init__.py    add.py    multiply.py

add.py:

def add(a, b):    return a + b

multiply.py:

def mul(a, b):    return a * b

__init__.py:

from .add import addfrom .multiply import mul
__all__ = ["add", "mul"]
print("mypkg loaded.")

用户端:

from mypkg import *
print(add(1, 2))print(mul(2, 5))

小结

__all__ 是 Python 模块化体系中极具工程价值的接口控制工具。它通过显式定义“允许被星号导入的名称”,使开发者能够严格管理对外 API,避免命名污染,并让大型包的结构清晰而稳定。它不影响普通导入,但能有效隔离内部实现,是构建高质量可维护库的重要机制。

熟练使用 __all__,意味着你不仅理解模块的组织方式,更真正理解了 Python 的“接口哲学”——清晰、显式、可控。

到此这篇关于Python中__all__用法及常见误区的文章就介绍到这了,更多相关Python __all__用法内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • 将自己的数据集制作成TFRecord格式教程

    将自己的数据集制作成TFRecord格式教程

    今天小编就为大家分享一篇将自己的数据集制作成TFRecord格式教程,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2020-02-02
  • 学会使用Python Configparser处理ini文件模块

    学会使用Python Configparser处理ini文件模块

    这篇文章主要为大家介绍了使用Python Configparser处理ini文件模块的学习,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2023-06-06
  • python matplotlib绘图,修改坐标轴刻度为文字的实例

    python matplotlib绘图,修改坐标轴刻度为文字的实例

    今天小编就为大家分享一篇python matplotlib绘图,修改坐标轴刻度为文字的实例,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2018-05-05
  • 一文掌握Python爬虫XPath语法

    一文掌握Python爬虫XPath语法

    这篇文章主要介绍了一文掌握Python爬虫XPath语法,xpath是一门在XML和HTML文档中查找信息的语言,可用来在XML和HTML文档中对元素和属性进行遍历,XPath 通过使用路径表达式来选取 XML 文档中的节点或者节点集。下面会更学习的介绍,需要的朋友可以参考一下
    2021-11-11
  • Python Flask JinJa2 语法使用示例详解

    Python Flask JinJa2 语法使用示例详解

    这篇文章主要为大家介绍了Python Flask JinJa2 语法示例详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2023-03-03
  • 使用python编写简单的小程序编译成exe跑在win10上

    使用python编写简单的小程序编译成exe跑在win10上

    这篇文章主要介绍了使用python编写简单的小程序编译成exe跑在win10上的相关资料,需要的朋友可以参考下
    2018-01-01
  • windows python嵌入式安装全过程

    windows python嵌入式安装全过程

    文章介绍了嵌入式安装包的概念,包括嵌入式Python和如何创建嵌入式安装包,嵌入式Python是一个精简版的Python解释器,可以在没有安装Python的环境中运行,文章还提供了下载和配置嵌入式Python的详细步骤,包括从官网下载安装包、下载get-pip.py、配置文件和环境变量等
    2024-11-11
  • Python容器转换与共有函数举例详解

    Python容器转换与共有函数举例详解

    Python容器是Python编程语言中非常基础且重要的概念,它们提供了数据的存储和组织方式,下面这篇文章主要介绍了Python容器转换与共有函数的相关资料,文中通过代码介绍的非常详细,需要的朋友可以参考下
    2025-12-12
  • 在Python的Flask框架中使用日期和时间的教程

    在Python的Flask框架中使用日期和时间的教程

    这篇文章主要介绍了在Python的Flask框架中使用日期和时间的教程,包括对各个时区之间转换的一些处理,需要的朋友可以参考下
    2015-04-04
  • Python中利用函数装饰器实现备忘功能

    Python中利用函数装饰器实现备忘功能

    这篇文章主要介绍了Python中利用函数装饰器实现备忘功能,同时还降到了利用装饰器来检查函数的递归、确保参数传递的正确,需要的朋友可以参考下
    2015-03-03

最新评论