10.1.2 模块是用来下定义的
模块在首次被导入程序时执行。这看似有点用,但用处不大。让模块值得被创建的原因在于它们像类一样,有自己的作用域。这意味着在模块中定义的类和函数以及对其进行赋值的变量都将成为模块的属性。这看似复杂,但实际上非常简单。
1. 在模块中定义函数
假设你编写了一个类似于代码清单10-2所示的模块,并将其存储在文件hello2.py中。另外,假设你将这个文件放在了Python解释器能够找到的地方(可像前一节介绍的那样使用sys.path,也可使用10.1.3节介绍的传统方式)。
提示 像处理模块那样,让程序(这意味着将被执行,而不是用作模块)可用后,可使用Python解释器开关-m来执行它。如果随其他模块一起安装了文件progname.py(请注意扩展名),即导入了progname,命令python -m progname args将使用命令行参数args来执行程序progname。
代码清单10-2 只包含一个函数的简单模块
# hello2.py
def hello():
print("Hello, world!")
现在可以像下面这样导入它:
>>> import hello2
这将执行这个模块,也就是在这个模块的作用域内定义函数hello,因此可像下面这样访问这个函数:
>>> hello2.hello()
Hello, world!
在模块的全局作用域内定义的名称都可像上面这样访问。为何要这样做呢?为何不在主程序中定义一切呢?
主要是为了重用代码。通过将代码放在模块中,就可在多个程序中使用它们。这意味着如果你编写了一个出色的客户数据库,并将其放在模块clientdb中,就可在记账时、发送垃圾邮件(但愿你不会这样做)时以及任何需要访问客户数据的程序中使用它。如果没有放在独立的模块中,就需在每个这样的程序中重新编写它。因此,要让代码是可重用的,务必将其模块化!(这也与
抽象紧密相关。)
2. 在模块中添加测试代码
模块用于定义函数和类等,但在有些情况下(实际上是经常),添加一些测试代码来检查情况是否符合预期很有用。例如,如果要确认函数hello管用,你可能将模块hello2重写为代码清单10-3所示的模块hello3。
代码清单10-3 一个简单的模块,其中的测试代码有问题
# hello3.py
def hello():
print("Hello, world!")
# 一个测试:
hello()
这看似合理:如果将这个模块作为普通程序运行,将发现它运行正常。然而,如果在另一个程序中将其作为模块导入,以便能够使用函数hello,也将执行测试代码,就像本章的第一个hello模块一样。
>>> import hello3
Hello, world!
>>> hello3.hello()
Hello, world!
这不是你想要的结果。要避免这种行为,关键是检查模块是作为程序运行还是被导入另一个程序。为此,需要使用变量__name__。
>>> __name__
'__main__'
>>> hello3.__name__
'hello3'
如你所见,在主程序中(包括解释器的交互式提示符),变量__name__的值是'__main__',而在导入的模块中,这个变量被设置为该模块的名称。因此,要让模块中测试代码的行为更合理,可将其放在一条if语句中,如代码清单10-4所示。
代码清单10-4 一个包含有条件地执行的测试代码的模块
# hello4.py
def hello():
print("Hello, world!")
def test():
hello()
if __name__ == '__main__': test()
如果将这个模块作为程序运行,将执行函数hello;如果导入它,其行为将像普通模块一样。
>>> import hello4
>>> hello4.hello()
Hello, world!
如你所见,我将测试代码放在了函数test中。原本可以将这些代码直接放在if语句中,但通过将其放在一个独立的测试函数中,可在程序中导入模块并对其进行测试。
>>> hello4.test()
Hello, world!
注意 如果要编写更详尽的测试代码,将其放在一个独立的程序中可能是个不错的主意。有关如何编写测试的详细信息,请参阅第16章。
领取专属 10元无门槛券
私享最新 技术干货