Python 模块 __all__变量用法

文摘   科技   2024-10-11 09:55   上海  

点击蓝字,关注山海摸鱼人

使用__all__结合from 模块名 import *可以帮助你控制对外公开的API,防止不必要的成员被暴露。

Python模块__all__变量示例

第一步:创建项目结构

首先,你需要在你的计算机上建立一个工作目录,并在这个目录下创建几个文件。这些文件将代表我们的不同模块。这里是一个简单的示例结构:

fish_project/

├── main.py
├── fish_data.py
└── fishing_tools.py
  • main.py 是主程序入口。
  • fish_data.py 将包含一些数据和函数,用于处理关于鱼的信息。
  • fishing_tools.py 将提供一些工具函数,帮助我们更有效地“捕鱼”。
第二步:编写fish_data.py模块

接下来,我们在fish_data.py中定义一些基本的数据和函数。这个模块将模拟一个鱼类数据库,并提供查询功能。

# fish_data.py
def chaxun_yu_mingcheng(yu_id):
    """根据鱼的ID查询鱼的名字"""
    yu_zidian = {
        1'鲤鱼',
        2'草鱼',
        3'鲫鱼'
    }
    return yu_zidian.get(yu_id, '未知鱼种')

def jisuan_yu_zhonglei_shuliang():
    """计算鱼类种类数量"""
    return len(chaxun_yu_mingcheng.__globals__.get('yu_zidian', {}))

# 这里我们定义了 __all__ 来指定当其他模块从当前模块导入*时,可以使用的名称
__all__ = ['chaxun_yu_mingcheng']

注意,在上面的例子中,我们通过__all__列表指定了只有chaxun_yu_mingcheng函数可以在使用from fish_data import *时被直接访问到。这意味着jisuan_yu_zhonglei_shuliang不会被导入,除非明确地指定它。

第三步:编写fishing_tools.py模块

现在,让我们为项目添加一些有用的工具。fishing_tools.py可能包括一些辅助函数,比如格式化输出或数据转换等。

# fishing_tools.py
def da_yin_jieshao(xinxi):
    """打印一条信息,附带装饰性的边框"""
    print('=' * 40)
    print(xinxi.center(40))
    print('=' * 40)

# 同样,我们也设置了 __all__ 列表
__all__ = ['da_yin_jieshao']
第四步:整合所有内容于main.py

最后,我们需要在main.py中整合所有的代码片段。这将作为整个项目的起点,同时也是展示__all__作用的地方。

# main.py
# 导入必要的模块
from fish_data import *
import fishing_tools as ft

# 使用fish_data模块提供的功能
print("查询ID为2的鱼名:")
print(chaxun_yu_mingcheng(2))  # 应该输出: 草鱼

# 注意,尝试调用未被导出的函数会引发NameError
# print(jisuan_yu_zhonglei_shuliang())  # 如果取消注释,会导致错误

# 使用fishing_tools模块的功能
ft.da_yin_jieshao('欢迎来到山海摸鱼人的世界!')

通过上述例子,你可以看到__all__是如何控制哪些名字可以被外部直接访问的。这种方式有助于保持接口清晰,并且避免了命名冲突的问题。

Python 模块导入注意事项

以下是关于__all__变量及不同导入方法的关键注意事项:

1、使用 from 模块名 import * 导入:

  • 当一个模块定义了__all__列表,并且你使用from 模块名 import *的形式来导入这个模块时,只有__all__列表中明确列出的成员会被导入。
  • 任何未在__all__列表中指定的成员将不会被导入到当前命名空间。这意味着即使模块内存在这些成员,它们也不会自动出现在你的代码中。
  • 这种做法有助于限制从外部访问的接口,减少命名冲突的可能性,并且可以提高代码的安全性和清晰度。

2、使用 import 模块名 导入:

  • 通过这种方式导入模块后,你可以通过模块名前缀(或别名)来访问模块内的所有非私有成员。例如,如果模块名为fish_data,你可以通过fish_data.成员名的方式访问其内部函数或变量。
  • 私有成员(即以单下划线_开头的名称)通常被认为是仅供模块内部使用的,不应直接从外部访问。虽然技术上仍然可以通过这种形式访问,但这样做是不推荐的,因为它违背了设计意图。
  • 使用完整的模块名作为前缀可以帮助避免命名冲突,并且使得代码更加易于理解。

3、使用 from 模块名 import 成员 导入:

  • 这种方式允许你直接导入并使用特定的成员,而不需要通过模块名作为前缀。例如,from fish_data import chaxun_yu_mingcheng可以直接让你使用chaxun_yu_mingcheng函数。
  • 即使模块中设置了__all__列表,当你明确指定了要导入的成员时,__all__设置将不起作用。也就是说,无论该成员是否列在__all__中,都可以成功导入。
  • 这种导入方式可以使代码更简洁,但如果过度使用,可能会导致命名空间污染和潜在的命名冲突问题。因此,建议谨慎选择要直接导入的成员。

山海摸鱼人
致力于记录美好之瞬间,追寻美好之明天。
 最新文章