Python之模块高级话题
本文大纲:
1. 在模块中隐藏数据
有两个模块分别是:
a.py
b.py
现在要在b.py中导入模块a.py。当我们在b.py中导入a.py时,Python会导出a.py顶层所赋值的所有变量名。有时我们会有这样的需求,只要导入a.py中的部分变量名,不用全部导入,这时该怎么做呢?这时就引入我们今天讲的第一点在模块中隐藏数据。
1.1 最小化 from *
的破坏:_X
和 __all__
当我们使用 from *
在b.py导入a.py模块时,from *
会把a.py全部的变量名都复制过去,有些变量名不是我们需要的,如果a.py和b.py有同名的变量名,a.py的变量名还会覆盖b.py的变量名。
在a.py文件内的变量名前面放置单下划线,可以防止使用 from *
导入模块时,将其中的变量名复制过去。例如: _name
, _age
,_address
...
也可以在模块顶层把变量名的字符串列表赋值给变量 __all__
,以达到类似于 _X
的隐藏效果。例如:
__all__ = ["score", "class", "school"]
_X
和 __all__
的区别
from *
会把列在__all__
列表中的这些变量名复制出来__all__
指出要复制的变量名,而_X
是指出不被复制的变量名- Python会先找模块内的
__all__
列表,如果没有定义的话, from * 就会复制出开头没有单下划线的所有变量名。 __all__
和_X
只对from *
语句这种形式有效,它并不是私有声明。
启用新版本的语言特性 __future__
Python中的每个新版本都会增加一些新功能,或者在原来版本的基础上做一些修改。有的在当前版本运行正常的代码,可能到了下个新版本就运行不正常了。我们可以使用 __future__
模块,把下一个版本的新特性引入到当前版本,这样就可以在当前版本测试新版本的特性了。例如:
from __future__ import featurename
混合用法模式: __name__
和 __main__
可以把这个文件作为模块导入,并以独立程序的形式运行。每个模块都会有一个 __name__
属性,Python会自动设置该属性。
- 如果文件是以顶层文件执行,在启动时,
__name__
就会设置为字符串"__main__
"。 - 如果文件被导入,
__name__
就会改设成客户端所了解的模块名。
结果就是模块可以检测自己的 __name__
,来确定它是在执行还是在导入。
下面是一个名为 runme.py 的模块文件。当此文件以程序执行时,就会调用该函数的代码,注意看print(__name__)
的结果:
def tester():
print("Hello World!")
print(__name__)
if __name__ == '__main__':
tester()
运行结果:
Hello World!
__main__
下面创建一个 test.py 文件,runme.py以模块的形式导入使用,注意看print(name)的结果:
import test
test.tester()
运行结果:
Hello World!
test
一个模块的 __name__
变量充当一个使用模式标志,允许它编写成一个可导入的库和一个顶层脚本。
以 __name__
进行单元测试
下面的函数用于计算一组传进来的数的最小值
def minmax(test,*args):
res = args[0]
for arg in args[1:]:
if test(arg, res):
res = arg
return res
def lessthan(x,y): return x < y
def grtrthan(x,y): return x > y
print(minmax(lessthan, 4, 2, 1, 5, 6, 3))
print(minmax(grtrthan, 4, 2, 1, 5, 6, 3))
这个脚本在末端的最后两个print语句是这个程序自我测试的代码。但是这种写法有一个问题,每次这个文件被另一个文件当做模块导入时,都会调用最后两个print语句并输出结果,这对用户体验来说很不好。现做如下改进:
def minmax(test,*args):
res = args[0]
for arg in args[1:]:
if test(arg, res):
res = arg
return res
def lessthan(x,y): return x < y
def grtrthan(x,y): return x > y
if __name__ == '__main__':
print(minmax(lessthan, 4, 2, 1, 5, 6, 3))
print(minmax(grtrthan, 4, 2, 1, 5, 6, 3))