zoukankan      html  css  js  c++  java
  • 第10.5节 使用__all__定义Python模块导入白名单

    一、 引言
    《第10.4节 Python模块的弱封装机制》介绍了Python模块的的弱封装机制,除了使用弱封装机制来从一定程度上防止导入特定成员外,Python模块中还提供可另外一种类似白名单的机制来控制导入的成员,这个机制就是在模块中定义__all__变量,将__all__的值设置成一个列表,只有列表中的模块成员才能被导入。

    二、 方法介绍
    在模块内部定义一个模块内的全局变量__all__,其元素是每个需要允许导出的成员名字符串。
    all = [‘成员名1’,…,‘成员名n’]

    三、 案例
    1、 我们定义一个imptest模块,包括三个成员变量和5个成员函数,内容如下:

    #imptest.py
    __all__=['f','_f1','var2','_var3']
    var1,var2,_var3='imptest var1','imptest var2','imptest _var3'
    _var2
    def f():
        print("execute ftest function in imptest....")
    def _f1():
        print("execute _f1(单下划线开头) function in imptest....")
    def __f2():
        print("execute __f2(双下划线开头) function in imptest....")
    def __f3__():
        print("execute __f3__(双下划线开头结尾) function in imptest....")
    def f4():
        print("execute f4 function in imptest....")
        
    print("Now in imptest module!")  
    

    2、 使用“from 模块名 import *”导入imptest模块的成员并执行验证是否导入成功

    >>> from imptest import *
    Now in imptest module!
    >>> var1
    Traceback (most recent call last):
      File "<pyshell#1>", line 1, in <module>
        var1
    NameError: name 'var1' is not defined
    >>> var2
    'imptest var2'
    >>> _var3
    'imptest _var3'
    >>> f()
    execute ftest function in imptest....
    >>> _f1()
    execute _f1(单下划线开头) function in imptest....
    >>> __f2()
    Traceback (most recent call last):
      File "<pyshell#6>", line 1, in <module>
        __f2()
    NameError: name '__f2' is not defined
    >>>
    

    执行截图:
    在这里插入图片描述
    从上述执行情况来看,只有在__all__列表中的成员才能通过“from imptest import *”导入,带下划线的也会正常导入,没有在__all__列表中的成员计算无下划线开头也不能导入。
    3、 直接使用“import 模块名”导入
    源代码:

    >>> import imptest
    Now in imptest module!
    >>> imptest.f()
    execute ftest function in imptest....
    >>> imptest._f1()
    execute _f1(单下划线开头) function in imptest....
    >>> imptest.__f2()
    execute __f2(双下划线开头) function in imptest....
    >>> imptest.__f3__()
    execute __f3__(双下划线开头结尾) function in imptest....
    >>> imptest.var1,imptest.var2,imptest._var3
    ('imptest var1', 'imptest var2', 'imptest _var3')
    >>>
    

    执行截屏:
    在这里插入图片描述
    从上述执行情况来看,使用“import 模块名”导入后,所有成员都可以正常访问,不受__all__列表的影响。

    四、 总结
    使用__all__定义模块访问白名单:

    1. 只对“from 模块名 import *”导入产生影响,对“import 模块名”或“from 模块名 import 成员名”不产生影响;
    2. 在__all__列表中的元素不论是否带下划线开头,“from 模块名 import *”都会导入,不受模块的缺省封装机制影响,可以说这是另一种方式的封装;
    3. 在模块定义__all__变量后,可以使用“模块.__all__”查看模块建议使用的模块成员。

    __all__变量可以认为给模块定义了一个开放的公共接口。通常来说,只有__all__变量列出的模块属性,才是该模块建议外界使用的。因此,为一个大模块定义__all__ 变量,就可以给调用程序建议过滤不需要使用的变量、函数和类,只使用__all__定义的白名单属性。

    前面章节介绍过 dir(模块名)可返回模块或类所包含的全部程序单元(包括变量、函数、类和方法等),但直接使用 dir() 函数默认会列出模块内所有的属性,包括以下划线开头的属性,如果模块定义了__all__ 变量,则建议调用者只关注__all__ 变量限定的属性。

  • 相关阅读:
    大假期第二次测试总结
    大假期第一次测试
    拦截导弹简单版——线性dp
    我的vim配置
    2E Bank Hacking——思维题
    2D poj Cow Relays——folyd+矩阵快速幂
    2C Numerical Sequence (hard version)
    2A Subset——折半枚举+二分
    2B 米特运输
    偷天换日——树状DP
  • 原文地址:https://www.cnblogs.com/LaoYuanPython/p/13643655.html
Copyright © 2011-2022 走看看