模块有什么用呢?何不把所有的 py 代码都放在一个文件中呢?
大量代码在一个文件中,不易于维护,大量的代码会让人眼花缭乱,我们根据功能不同分为多个文件,那么维护的时候就很方便了。
从另一方面,我们会写一些比较有用的代码,我们将其封装为单独的模块,下次使用此功能的时候就不需要重写编写代码,达到复用的效果,我们的程序也不需要每次都从零开始。
封装为单独的模块,还可以解决命名冲突的问题,不同模块中的名字是可以重复的。但是同一模块中名字是不可以重复的。达到复用名字的效果。
- 使用模块 {#title-0} ==================
Python 中的模块指的是一个包含的各种 Python 对象的程序文件。
1.1 模块使用 {#title-1}
我们编写一个模块,命名为 my_module.py,在该模块中我们定义一些函数和类,如下代码所示:
# Person类
class Person(object):
def __init__(self,name,age):
self.name = name
self.age = age
def show_person(self):
print("Name:%s Age:%d"%(self.name,self.age))
# 函数
def my_add(a,b):
ret = a + b
return ret
我们在其他 Python 文件中使用时,首先需要导入这些需要的对象,导入方法如下:
- import 模块名
- import 模块名 as 别名
- from 模块名 import 符号
- from 模块名 import 符号 as 别名
- from 模块名 import *
# 1. import 模块名
import mymodule
print(mymodule.my_add(10, 20))
# 2. import 模块名 as 别名
import mymodule as mm
print(mm.my_add(10, 20))
# 3. from 模块名 import 符号
from mymodule import Person
person = Person('smith', 18)
person.show_person()
# 3. from 模块名 import 符号 as 别名
from mymodule import Person as P
from mymodule import my_add as ma
p = P('obama', 20)
p.show_person()
print(ma(10, 20))
# 4. from 模块名 import *
from mymodule import *
person = Person('smith', 18)
person.show_person()
1.2 main {#title-2}
如果我们的 my_module 模块内容如下:
def my_addd():
print('a + b = %d' % (a + b))
# 测试代码,或者其他一些代码
my_add(10, 20)
当 my_module 作为模块被 import 到其他文件中时,上面的 my_add 函数调用就会被自动执行。我们可以进行如下改进来避免此问题:
def my_addd():
print('a + b = %d' % (a + b))
# 测试代码或者其他一些代码,避免被作为模块导入时被执行
if __name__ == '__main__':
my_addd(10, 20)
所以,if main 的作用就是避免某个 Python 模块被导入时自动执行一些测试代码。
- 包 {#title-3} ===============
为了更好管理模块,将多个模块放到一个文件夹中,这个文件夹就叫做包,但是此文件夹下必须包含**init.py** 文件,该__init__文件可以为空。__init__文件主要用于标识该目录是一个包。我们接下来构建一个名字叫叫做 package 的 Python 包,目录结构如下:
package
|-- __init__.py
|-- my_module1.py
`-- sub_package
|-- __init__.py
`-- my_module2.py
2.1 使用包 {#title-4}
# 1. import 模块名
import package.my_module1
import package.sub_package.my_module2
package.my_module1.my_function1()
package.sub_package.my_module2.my_function2()
# 2. import 模块名 as 别名
import package.my_module1 as p
import package.sub_package.my_module2 as sp
p.my_function1()
sp.my_function2()
# 3. from 模块名 import 符号
from package.my_module1 import my_function1
from package.sub_package.my_module2 import my_function2
my_function1()
my_function2()
# 4. from 模块名 import *
from package.my_module1 import *
from package.sub_package.my_module2 import *
my_function1()
my_function2()
2.2 init.py 文件的作用 {#title-5}
init 文件中一般用来编写一些模块的初始化代码或者其他一些用于简化 import 的代码。这一部分我们通过案例描述。目录结构为:
.
|-- main.py
`-- package
|-- __init__.py
|-- my_module1.py
`-- sub_package
|-- __init__.py
|-- my_module2.py
package 中 定义 my_function1 函数,sub_package/my_module2 中定义 my_function2 函数。包的目录结构会导致导入包时编写的路径较长,我们可以使用 init 文件来简化这个步骤。
sub_packgae/init.py 文件内容如下:
from package.sub_package.my_module2 import *
执行效果就是将 my_module2 中的 my_funtion2 提到了 sub_package 空间中,如下图所示:
其中 packgae/init.py 文件内容如下:
from package.my_module1 import *
from package.sub_package import *
这两行代码,将 sub_package 中的 my_function2 和 my_module1 中的 my_function1 提升到了 package 空间中,如下图所示:
当我们在 main 中导包时,就可以直接通过顶层包名来导入某个具体符号,如下代码所示:
# 通过包名直接导入模块中定义的符号
from package import my_function2
from package import my_function1