2022年 11月 7日

python模块的定义,和模块的作用域

模块: 为了编写可维护的代码,我们把很多函数分组,分别放到不同的文件里,这样,每个文件包含的代码就相对较少,很多编程语言都采用这种组织代码的方式。在Python中,一个.py文件就称之为一个模块(Module)。

优点:最大的好处是大大提高了代码的可维护性。其次,编写代码不必从零开始。当一个模块编写完毕,就可以被其他地方引用。我们在编写程序的时候,也经常引用其他模块,包括Python内置的模块和来自第三方的模块。使用模块还可以避免函数名和变量名冲突。相同名字的函数和变量完全可以分别存在不同的模块中,因此,我们自己在编写模块时,不必考虑名字会与其他模块冲突。但是也要注意,尽量不要与内置函数名字冲突。

包:如果不同的人编写的模块名相同怎么办?为了避免模块名冲突,Python又引入了按目录来组织模块的方法,称为包(Package)。举个例子,一个abc.py的文件就是一个名字叫abc的模块,一个xyz.py的文件就是一个名字叫xyz的模块。假设我们的abcxyz这两个模块名字与其他模块冲突了,于是我们可以通过包来组织模块,避免冲突。方法是选择一个顶层包名,比如mycompany,按照如下目录存放:

  1. mycompany
  2. ├─ __init__.py
  3. ├─ abc.py
  4. └─ xyz.py

引入了包以后,只要顶层的包名不与别人冲突,那所有模块都不会与别人冲突。现在,abc.py模块的名字就变成了mycompany.abc,类似的,xyz.py的模块名变成了mycompany.xyz

请注意,每一个包目录下面都会有一个__init__.py的文件,这个文件是必须存在的,否则,Python就把这个目录当成普通目录,而不是一个包。__init__.py可以是空文件,也可以有Python代码,因为__init__.py本身就是一个模块,而它的模块名就是mycompany。 

类似的,可以有多级目录,组成多级层次的包结构。比如如下的目录结构:

  1. mycompany
  2. ├─ web
  3. │ ├─ __init__.py
  4. │ ├─ utils.py
  5. │ └─ www.py
  6. ├─ __init__.py
  7. ├─ abc.py
  8. └─ utils.py

 模块的规范写法:

  1. #!/usr/bin/env python3
  2. # -*- coding: utf-8 -*-
  3. ' a test module '
  4. __author__ = 'Michael Liao'
  5. import sys
  6. def test():
  7. args = sys.argv
  8. if len(args)==1:
  9. print('Hello, world!')
  10. elif len(args)==2:
  11. print('Hello, %s!' % args[1])
  12. else:
  13. print('Too many arguments!')
  14. if __name__=='__main__':
  15. test()

第1行和第2行是标准注释。第1行注释可以让这个hello.py文件直接在Unix/Linux/Mac上运行,第2行注释表示.py文件本身使用标准UTF-8编码;

第3行是一个字符串,表示模块的文档注释,任何模块代码的第一个字符串都被视为模块的文档注释;

第4行使用__author__变量把作者写进去,这样当你公开源代码后别人就可以瞻仰你的大名;

以上就是Python模块的标准文件模板,当然也可以全部删掉不写,但是,按标准办事肯定没错。

后面开始就是真正的代码部分。

最后两行代码:命令行运行hello模块文件时,Python解释器把一个特殊变量__name__置为__main__,而如果在其他地方导入该hello模块时,if判断将失败,因此,这种if测试可以让一个模块通过命令行运行时执行一些额外的代码,最常见的就是运行测试。

作用域:

1.正常的函数和变量名是公开的(public),可以被直接引用,比如:abcx123PI等;

2.类似__xxx__这样的变量是特殊变量,可以被直接引用,但是有特殊用途,比如上面的__author____name__就是特殊变量,hello模块定义的文档注释也可以用特殊变量__doc__访问,我们自己的变量一般不要用这种变量名;

3.类似_xxx__xxx这样的函数或变量就是非公开的(private),不应该被直接引用,比如_abc__abc等;

外部不需要引用的函数全部定义成private,只有外部需要引用的函数才定义为public。