一、导入同级目录文件

如果需要引入同级目录下的文件,则可以采用import一个模块的形式,即可调用。
考虑同一目录下的两个python文件,test.py 需要调用support.py 中的函数,目录结构如下:

  1. demo
  2. |-- test.py
  3. |-- support.py

support.py 中的代码如下:

  1. #!/usr/bin/env python3
  2. # -*- coding: utf-8 -*-
  3. ' a test module '
  4. __author__ = '小黄牛'
  5. def test(param):
  6. print('您好:', param)

test.py 调用的代码如下:

  1. #!/usr/bin/env
  2. # -*- coding: UTF-8 -*-
  3. # 导入模块
  4. import support
  5. # 现在可以调用模块里包含的函数了
  6. support.test('小黄牛')

上面的support.py代码中,
第1行和第2行是标准注释,
第1行注释可以让这个support.py文件直接在Unix/Linux/Mac上运行,
第2行注释表示.py文件本身使用标准UTF-8编码;
第4行是一个字符串,表示模块的文档注释,任何模块代码的第一个字符串都被视为模块的文档注释;
第6行使用__author__变量把作者写进去,这样当你公开源代码后别人就可以瞻仰你的大名;
以上就是Python模块的标准文件模板,当然也可以全部删掉不写,但是,按标准办事肯定没错。
后面开始就是真正的代码部分。

这种自定义模块的写法,一般是用于解释器模式下调用的,如果我们需要让模块支持命令行模式传递参数,就需要使用到系统自带的sys模块,下面我们将support.py文件修改为以下代码:

  1. #!/usr/bin/env python3
  2. # -*- coding: utf-8 -*-
  3. ' a test module '
  4. __author__ = '小黄牛'
  5. # 导入系统的sys模块
  6. import sys
  7. def test(param='小黄牛'):
  8. # 获取系统命令行参数
  9. args = sys.argv
  10. print(args)
  11. # 打印自定义参数
  12. print(param)
  13. if __name__=='__main__':
  14. test()

导入sys模块后,我们就有了变量sys指向该模块,利用sys这个变量,就可以访问sys模块的所有功能。
sys模块有一个argv变量,用list存储了命令行的所有参数。
argv至少有一个元素,因为第一个参数永远是该.py文件的完整路径,例如:
运行python3 test.py获得的sys.argv就是['完整路径/test.py']
运行python3 test.py JunHao获得的sys.argv就是['完整路径/test.py', 'JunHao']

最后,注意到这两行代码:

  1. if __name__=='__main__':
  2. test()

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

二、导入子目录文件

如果需要引入子目录下的文件,则可以采用import一个包的形式,将子目录封装成包,即可调用。
考虑一个在 functions 目录下的 run1.pyrun2.py__init__.py 文件,test.py 为测试调用包的代码,目录结构如下:

  1. test.py
  2. functions
  3. |-- __init__.py
  4. |-- run1.py
  5. |-- run2.py

注意:__init__.py可以是空文件。

test.py 调用代码如下:

  1. #!/usr/bin/env
  2. # -*- coding: UTF-8 -*-
  3. # 导入模块包
  4. # 引入 /functions/run1.py 里的 run1()方法
  5. from functions.run1 import run1
  6. from functions.run2 import run2
  7. run1()
  8. run2()

当然,也可以这样使用:

  1. #!/usr/bin/env
  2. # -*- coding: UTF-8 -*-
  3. # 导入模块包
  4. import function.run1
  5. import function.run2
  6. functions.run1.run1()
  7. functions.run2.run2()

run1.py 代码如下:

  1. #!/usr/bin/env python3
  2. # -*- coding: utf-8 -*-
  3. ' a test module '
  4. __author__ = '小黄牛'
  5. def run1():
  6. print('run1 Hello!')

run2.py 代码如下:

  1. #!/usr/bin/env python3
  2. # -*- coding: utf-8 -*-
  3. ' a test module '
  4. __author__ = '小黄牛'
  5. def run2():
  6. print('run2 Hello!')

三、作用域

在一个模块中,我们可能会定义很多函数和变量,但有的函数和变量我们希望给别人使用,有的函数和变量我们希望仅仅在模块内部使用。
在Python中,是通过_前缀来实现的。

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

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

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

之所以我们说,private函数和变量“不应该”被直接引用,而不是“不能”被直接引用,是因为Python并没有一种方法可以完全限制访问private函数或变量,但是,从编程习惯上不应该引用private函数或变量。

private函数或变量不应该被别人引用,那它们有什么用呢?
请看例子,先修改run1.py中的代码:

  1. #!/usr/bin/env python3
  2. # -*- coding: utf-8 -*-
  3. ' a test module '
  4. __author__ = '小黄牛'
  5. def _private_1(name):
  6. return 'Hello, %s' % name
  7. def _private_2(name):
  8. return 'Hi, %s' % name
  9. def greeting(name):
  10. if len(name) > 3:
  11. return _private_1(name)
  12. else:
  13. return _private_2(name)

再修改test.py中的代码,然后运行:

  1. #!/usr/bin/env
  2. # -*- coding: UTF-8 -*-
  3. # 导入模块包
  4. import function.run1
  5. import function.run2
  6. print(function.run1.greeting('小黄牛'))
  7. function.run2.run2()

我们在模块里公开greeting()函数,而把内部逻辑用private函数隐藏起来了,这样,调用greeting()函数不用关心内部的private函数细节,这也是一种非常有用的代码封装和抽象的方法,即:

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