Python __all__

2025年1月5日 | 阅读 4 分钟

您是否曾经将一个 Python 文件导入到另一个 Python 代码中,然后使用该文件中的变量? 在这种情况下,第一个文件中的所有变量都可以在第二个文件中使用。 在本文中,我们将介绍一个这样的 Python 模块,即 __all__,它允许用户在 Python 程序中导入特定变量,而不是全部导入。

Python 中的 __all__ 是什么意思?

在 Python 中,__all__ 是一个字符串列表,指定哪些变量必须导入到另一个文件中。 只有导入此文件后,您才能在另一个文件中使用在该列表中定义的变量; 否则,在尝试使用其他变量时会发生错误。

当模块使用 from module import * 行导入时,__all__ 列表指定了要导出的公共对象的名称。

不在 __all__ 中的项将不允许在导入模块中使用,也不会被导出。

考虑以下示例。

在这种情况下,mymodule 模块的公共接口由 fun1 函数和 fun2 类组成,但 fun3 函数是私有的,不应被外部代码访问。

当使用 from my module import * 行导入模块时,只有 fun1 和 fun2 将被导入到当前命名空间。

Python 中 __all__ 的好处

  • 安全目的: 出于安全原因,在 Python 文件之间导入数据时,第一个文件中的所有变量都可以用于第二个文件。 如果出于安全原因,我们只希望第二个文件使用第一个文件变量的一个子集而不是全部变量,那么可以使用第一个 Python 文件中的 __all__ 函数来指定可用变量。
  • 使用相同的变量名: 假设我们有一个在第一个 Python 文件中声明的名为 XYZ 的变量,并且另一个 Python 程序正在调用第一个 Python 文件,那么第一个文件中的所有变量都将被导入到第二个文件中。

python __all__ 最佳实践

在使用 Python 的 __all__ 属性时,应遵循一些指南

  • 使用 __all__ 来清晰地指定模块的公共接口。 这有助于其他开发人员了解哪些项仅用于内部使用,哪些项用于外部使用。
  • __all__ 列表应简洁且有针对性。 只应列出模块中属于公共 API 的对象。
  • 不要在代码中使用通配符导入 (from my module import*)。 相反,使用 import 语句导入特定对象。 这有助于避免命名冲突,并使正在使用的对象一目了然。
  • 将 __all__ 与详细的文档结合使用。 公共 API 中每个对象的预期用途和行为都应有详细记录。
  • 在所有模块中使用相同的语言。 这将使其他开发人员更容易理解如何使用您的代码。
  • 请记住,__all__ 仅影响 import('mymodule') 或 import(*) 通配符导入。 即使某个项没有完全导入,如果用户从您的模块中专门导入它,它仍将被导入。

python __all__ 函数示例

以下是使用 Python 模块中的 __all__ 变量的进一步说明

说明

  • 公共函数 (my_public_function):此函数旨在成为开放 API 的一部分。 其名称不带下划线前缀,表明它 intended for external usage。
  • 私有函数 (_my_private_function):在 Python 中,函数名称前的下划线表示它仅 intended for internal usage,并且不属于公共 API。 这是一个标准做法。
  • 公共变量 (my_var1):此变量的名称不包含下划线,表明它是公共 API 的一部分,并且可以从外部访问。
  • 私有变量 (_my_var2):此变量名称前的下划线表示它不属于公共 API,并且仅 intended for internal usage。
  • __all__ 属性:此特殊属性包含一个名称列表,这些名称被认为是公共 API 的一部分。 在此示例中,它包括公共变量 (my_var1) 和公共函数 (my_public_function)。

由于 my_public_function 和 my_var1 包含在此示例的所有内容中,因此导入 testmodule 的其他模块将能够使用它们。 由于它们不包含在所有内容中,因此 _my_var2 和 _my_private_function 不能被导出或在其他模块中使用。

python __all__ 函数的优点

在 Python 中使用 __all__ 属性有很多好处

  • 通过显式指定模块的公共接口,其他开发人员可以快速确定哪些组件仅 intended for internal use,哪些 intended for external use。
  • 使用 __all__ 通过提供更协调的关联来简化代码的理解。
  • 通过从模块中导入特定对象而不是使用通配符导入,可以限制与全局命名空间中的对象的命名冲突。
  • 使用 __all__ 实现清晰的文档,解释哪些项包含在公共编程接口中以及如何使用它们。
  • 在修改模块时,如果只修改内部对象而保留外部接口不变,则更容易保持向后兼容性。
  • 通过限制导入对象的数量并避免通配符导入,程序性能可能会得到提高。 这样,程序将只导入所需的内容。