一、导入同级目录文件
如果需要引入同级目录下的文件,则可以采用import
一个模块的形式,即可调用。
考虑同一目录下的两个python文件,test.py
需要调用support.py
中的函数,目录结构如下:
demo
|-- test.py
|-- support.py
support.py
中的代码如下:
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
' a test module '
__author__ = '小黄牛'
def test(param):
print('您好:', param)
test.py
调用的代码如下:
#!/usr/bin/env
# -*- coding: UTF-8 -*-
# 导入模块
import support
# 现在可以调用模块里包含的函数了
support.test('小黄牛')
上面的support.py
代码中,
第1行和第2行是标准注释,
第1行注释可以让这个support.py
文件直接在Unix/Linux/Mac
上运行,
第2行注释表示.py
文件本身使用标准UTF-8
编码;
第4行是一个字符串,表示模块的文档注释,任何模块代码的第一个字符串都被视为模块的文档注释;
第6行使用__author__
变量把作者写进去,这样当你公开源代码后别人就可以瞻仰你的大名;
以上就是Python模块的标准文件模板,当然也可以全部删掉不写,但是,按标准办事肯定没错。
后面开始就是真正的代码部分。
这种自定义模块的写法,一般是用于解释器模式下调用的,如果我们需要让模块支持命令行模式传递参数,就需要使用到系统自带的sys
模块,下面我们将support.py
文件修改为以下代码:
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
' a test module '
__author__ = '小黄牛'
# 导入系统的sys模块
import sys
def test(param='小黄牛'):
# 获取系统命令行参数
args = sys.argv
print(args)
# 打印自定义参数
print(param)
if __name__=='__main__':
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']
。
最后,注意到这两行代码:
if __name__=='__main__':
test()
当我们在命令行运行support
模块文件时,Python解释器把一个特殊变量__name__
置为__main__
,而如果在其他地方导入该support
模块时,if
判断将失败,因此,这种if测试可以让一个模块通过命令行运行时执行一些额外的代码,最常见的就是运行测试。
二、导入子目录文件
如果需要引入子目录下的文件,则可以采用import
一个包的形式,将子目录封装成包,即可调用。
考虑一个在 functions
目录下的 run1.py
、run2.py
、__init__.py
文件,test.py
为测试调用包的代码,目录结构如下:
test.py
functions
|-- __init__.py
|-- run1.py
|-- run2.py
注意:__init__.py
可以是空文件。
test.py
调用代码如下:
#!/usr/bin/env
# -*- coding: UTF-8 -*-
# 导入模块包
# 引入 /functions/run1.py 里的 run1()方法
from functions.run1 import run1
from functions.run2 import run2
run1()
run2()
当然,也可以这样使用:
#!/usr/bin/env
# -*- coding: UTF-8 -*-
# 导入模块包
import function.run1
import function.run2
functions.run1.run1()
functions.run2.run2()
run1.py
代码如下:
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
' a test module '
__author__ = '小黄牛'
def run1():
print('run1 Hello!')
run2.py
代码如下:
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
' a test module '
__author__ = '小黄牛'
def run2():
print('run2 Hello!')
三、作用域
在一个模块中,我们可能会定义很多函数和变量,但有的函数和变量我们希望给别人使用,有的函数和变量我们希望仅仅在模块内部使用。
在Python中,是通过_
前缀来实现的。
正常的函数和变量名是公开的(public),可以被直接引用,比如:abc
,x123
,PI
等;
类似__xxx__
这样的变量是特殊变量,可以被直接引用,但是有特殊用途,比如上面的__author__
,__name__
就是特殊变量,run
模块定义的文档注释也可以用特殊变量__doc__
访问,我们自己的变量一般不要用这种变量名;
类似_xxx
和__xxx
这样的函数或变量就是非公开的(private),不应该被直接引用,比如_abc
,__abc
等;
之所以我们说,private
函数和变量“不应该”被直接引用,而不是“不能”被直接引用,是因为Python并没有一种方法可以完全限制访问private
函数或变量,但是,从编程习惯上不应该引用private
函数或变量。
private
函数或变量不应该被别人引用,那它们有什么用呢?
请看例子,先修改run1.py
中的代码:
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
' a test module '
__author__ = '小黄牛'
def _private_1(name):
return 'Hello, %s' % name
def _private_2(name):
return 'Hi, %s' % name
def greeting(name):
if len(name) > 3:
return _private_1(name)
else:
return _private_2(name)
再修改test.py
中的代码,然后运行:
#!/usr/bin/env
# -*- coding: UTF-8 -*-
# 导入模块包
import function.run1
import function.run2
print(function.run1.greeting('小黄牛'))
function.run2.run2()
我们在模块里公开greeting()
函数,而把内部逻辑用private
函数隐藏起来了,这样,调用greeting()
函数不用关心内部的private
函数细节,这也是一种非常有用的代码封装和抽象的方法,即:
外部不需要引用的函数全部定义成private
,只有外部需要引用的函数才定义为public
。