【问题标题】:avoid sub-modules and external packages in a module's namespace避免模​​块命名空间中的子模块和外部包
【发布时间】:2018-10-17 23:00:53
【问题描述】:

我正在编写一个模块来加载数据集。我想保持接口/API 尽可能干净——所以我通过在它们的名称前加上__ 来隐藏内部函数和变量。惊人的。但是,我的模块导入了仍然出现在我的模块命名空间中的其他包(例如numpy),我该如何避免这种情况?

即我的文件看起来像:

加载器.py:

import numpy as np

__INTERNAL_VAR1 = True
EXTERNAL_VAR = True

def loadData():
    data = __INTERNAL_FUNC1()
    ...
    return data

def __INTERNAL_FUNC1():
    ...
    return data

当我导入我的模块 np 时:

> import Loader
> Loader.[TAB]
  Loader.EXTERNAL_VAR   Loader.loadData   Loader.np

【问题讨论】:

    标签: python module namespaces package


    【解决方案1】:

    如果您使用的自动完成功能正确实现,它应该尊重模块的__all__ 属性(如果已设置)。

    添加您的模块以该名称导出的所有名称的列表:

    __all__ = ['loadData', 'EXTERNAL_VAR']
    

    __all__ 变量用于确定在使用 from modulename import * 通配符导入时导入的名称,以及在记录模块时通过 help() 函数确定导入的名称。

    使用双下划线名称作为全局变量是没有意义的;开头的一个下划线将此类名称标记为“内部”(按照惯例)。

    【讨论】:

    • 嗯,酷!这也是隐藏我的内部变量的好方法吗?即我应该将__INTERNAL_VAR1 切换到INTERNAL_VAR1(因为在源代码中到处都有这么多下划线有点烦人),但只是从__all__ 中省略它?
    • @zhermes:是的,你也可以这样做。
    • Help(Loader) 只显示我放入__all__ 的东西,同样适用于from Loader import *,但我的ipython (ipython-0.13.2_python-2.7.3) 不是“荣誉”这个......并且仍然向我展示所有非私有变量
    • @zhermes:这是 iPython 中的一个可配置选项,请参阅 github.com/ipython/ipython/issues/1571。这真的是自动完成开发人员的选择,不管他们是否会尊重__all__,这不是 Python 本身的问题。
    【解决方案2】:

    另一种解决方案是创建一个__init__.py,其中包含导入所需函数和变量的行:

    from Loader import EXTERNAL_VAR,loadData
    

    此文件应放在包含您的模块的文件夹中:

    └── Loader
        ├── __init__.py
        └── Loader.py
    

    现在当您导入Loader 时,您只能直接访问EXTERNAL_VARloadData,而所有其他类和模块都在Loader.Loader. 中 此解决方案应独立于您的自动完成系统。

    【讨论】:

    • 我更喜欢这个。使用此解决方案,np 不会导入到__init__.py,因此Loader 没有np 属性。使用已接受的答案,将 np 排除在 __all__ 之外可能会使用制表符完成将其从显示中消除,但 Loader.np 仍在命名空间中。
    猜你喜欢
    • 2020-01-03
    • 2018-03-07
    • 1970-01-01
    • 2015-01-07
    • 1970-01-01
    • 1970-01-01
    • 2021-11-02
    • 2016-07-17
    • 2014-01-26
    相关资源
    最近更新 更多