第10.5节 使用__all__定义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
>>>
>>> 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__定义的白名单属性。

经验分享 程序员 微信小程序 职场和发展