Python入门之四十一:创建与导入自定义模块和包
1年前
阅读 1919
评论 0
喜欢 0
### 一、导入同级目录文件
如果需要引入同级目录下的文件,则可以采用`import`一个模块的形式,即可调用。
考虑同一目录下的两个python文件,`test.py` 需要调用`support.py` 中的函数,目录结构如下:
```
demo
|-- test.py
|-- support.py
```
`support.py` 中的代码如下:
```python
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
' a test module '
__author__ = '小黄牛'
def test(param):
print('您好:', param)
```
`test.py` 调用的代码如下:
```python
#!/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`文件修改为以下代码:
```python
#!/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']`。
最后,注意到这两行代码:
```python
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` 调用代码如下:
```python
#!/usr/bin/env
# -*- coding: UTF-8 -*-
# 导入模块包
# 引入 /functions/run1.py 里的 run1()方法
from functions.run1 import run1
from functions.run2 import run2
run1()
run2()
```
当然,也可以这样使用:
```python
#!/usr/bin/env
# -*- coding: UTF-8 -*-
# 导入模块包
import function.run1
import function.run2
functions.run1.run1()
functions.run2.run2()
```
`run1.py` 代码如下:
```python
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
' a test module '
__author__ = '小黄牛'
def run1():
print('run1 Hello!')
```
`run2.py` 代码如下:
```python
#!/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`中的代码:
```python
#!/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`中的代码,然后运行:
```python
#!/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`。
© 著作权归作者所有