# 模块

前面提到的函数是一种模块化编程,它将一个功能包装为一个函数,在需要的时候调用它,这里说的模块更像是一个文件夹,它有很多文件,每个文件里很多函数,通过导入这个模块就能使用这里面的函数。Python包含了一组自带的模块,它们被称为标准库,它们为Python提供了很多功能。

# 导入模块

它有两种语法,一种是将模块整个导入,另一种是导入模块的某个函数。

import sys as MySys,random as MyRandom

print(MySys.argv)
print(MyRandom.random())

from time import *
print(gmtime())
from random import random
print(random())
1
2
3
4
5
6
7
8
9

# 定义模块

我们可以定义自己的模块,前面我们自己写的所有Python程序都可作为模块导入,作为模块导入的好处是这些模块可以被重复使用:

PersonModule.py文件内容:

'''
这是一个我们自己定义的模块
Person:这是一个模板类
'''

class Person:
    def Walk(self):
        print("He is walking!")
    def Eat(self):
        print("He is eatting!")

def test_person_walk():
    p = Person()
    p.Walk()

def test_person_eat():
    p = Person()
    p.Eat()

if __name__=='__main__':
    test_person_walk()
    test_person_eat()

print("__name__:%s" % __name__)

print("Person module is imported!")
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26

定义一个模块要做的事情:

  1. 编写说明文档。
  2. 编写模块主程序。
  3. 编写测试程序。

注意当上面的模块被python直接运行时,此时__name__是'main',这个时候测试程序才会运行,否则当模块作为模块被导入时,是不会运行测试程序的。

# 加载模块

下面来加载这个模块,在与PersonModule.py同一个文件夹的另一个文件中:

import PersonModule
p = PersonModule.Person()
p.Walk()

from PersonModule import Person
p2 = Person()
p2.Eat()

print(PersonModule.__doc__)

import sys,pprint
#查看Python的默认模块加载路径
pprint.pprint(sys.path)
1
2
3
4
5
6
7
8
9
10
11
12
13

注意:

  1. 在import的时候Python是根据环境变量PYTHONPATH来查找模块的,这些变量默认都会包含当前目录。
  2. 使用import导入模块,是把模块中的全部代码加载到内存并执行,然后将整个模块内容赋给与模块文件名同名的变量,该模块中定义的所有程序单元都相当于该变量的成员;使用from...import导入模块,把模块中的全部代码加载到内存,然后只导入指定变量,函数等成员。
  3. 不管使用何种方式导入,导入模块的时候,模块中的代码都会运行一遍,重复导入,只运行一次。
  4. 在模块文件夹下有__pycache__文件夹,其中有pyc文件,该文件其实是为模块编译生成的字节码,用于提升该模块的运行效率。

# __all__变量

默认情况下,使用from 模块名 import * 这个语句来导入模块,会导入该模块中所有不以双下划线开头的程序单元,而__all__变量则是设置一个列表,这个列表之外的单元都不会被暴露。如果想要导入列表之外的部分,可以:

  1. 使用import 模块名,来导入模块。
  2. 使用from 模块名 import 程序单元,来导入指定程序单元。
'''
测试__all__变量
'''

def test1():
    print("this is test1")
def test2():
    print("this is test2")
def test3():
    print("this is test3")

__all__=["test1","test2"]
1
2
3
4
5
6
7
8
9
10
11
12

测试__all__变量:

from PersonModule import *
test1()

#import PersonModule
#PersonModule.test3()

from PersonModule import test3
test3()
1
2
3
4
5
6
7
8

#

前面的模块只是一个文件,包是一个文件夹,在该文件夹下包含了一个__init__.py文件,由该文件再包含它包里面的其他文件,当外部导入一个包时,就导入了这个包里的所有文件。

# 定义包

在一个MyPackage文件夹下,__init__.py文件内容:

'''
这是定义的第一个包。
'''
#from . import Student
from .Student import *
#from . import Person
from .Person import *
1
2
3
4
5
6
7

Student.py文件内容:

def student():
    print("this is a student activity!")
1
2

Person.py文件内容:

def Eat():
    print("I am eatting!")
def Walk():
    print("I am walking!")
1
2
3
4

跳出这个文件夹,开一个测试文件:

import MyPackage
MyPackage.Walk()
MyPackage.Eat()
MyPackage.Student.student()

print(MyPackage.__doc__)
#查看包的位置
print(MyPackage.__file__)
print(dir(MyPackage))
print([e for e in dir(MyPackage) if not e.startswith("__")])
1
2
3
4
5
6
7
8
9
10

注意在__init__.py文件中只有from .Student import *,也可以在导入包时使用MyPackage.Student.方法名。