目录

Python面向对象(6)模块和包

Python面向对象(6)模块和包

学习目标

  • 了解模块
  • 导入模块
  • 制作模块
  • __all__
  • 包的使用方法

模块

在Python中模块(Module)是一个Python文件,以.py结尾,包含了Python对象定义和Python语句,模块能定义函数,类和变量,模块里也能包含可执行的代码。


导入模块

  • import 模块名
  • from 模块名 import 功能名
  • from 模块名 import *
  • import 模块名 as 别名
  • from 模块名 import 功能名 as 别名

import 模块名

语法:

1
2
3
4
5
import 模块名
import 模块1, 模块2

# 调用
模块名.功能名()

体验:

1
2
import math
print(math.sqrt(9))

from 模块名 import 功能名

语法:

1
2
3
from 模块名 import 功能名
# 调用
功能名()

体验:

1
2
from math import sqrt
print(sqrt(9))

from 模块名 import *

语法:

1
2
3
from 模块名 import * # *代表模块中的所有功能
# 调用
功能名()

体验:

1
2
from math import *
print(sqrt(9))

as 定义别名

语法:

1
2
import 模块名 as 别名 # 使用了别名就不能在使用模块名调用
from 模块名 import 功能名 as 别名 # 使用了别名就不能使用功能名

体验:

1
2
3
4
5
6
7
import math as mt
print(mt.sqrt(9))
print(math.mt) # 报错,math模块名已经弃用

from math import sqrt as st
print(st(9))
print(sqrt(9)) # 报错,功能名sqrt已经弃用

制作模块

在Python中,每个Python文件都可以作为一个模块,模块的名字就是文件的名字,也就是说自定义模块名必须要符合标识符命名规则。把需要频繁使用的类,方法,变量等代码封装到一个模块中,直接调用会使代码量更少,结构更简单。

定义模块

新建一个Python文件,命名为my_module.py,并定义testA函数。

1
2
def testA(a,b):
  return a+b

测试模块

在实际开发中,当一个开发人员编写完一个模块后,为了让模块能够在项目中达到想要的效果,这个开发人员会自行在py文件中添加一些测试信息,例如,在my_module.py文件中添加测试代码。

1
2
3
4
5
def testA(a,b):
    return a+b

# 测试一下
print(testA(1,3))  	# 4  # 测试完成后如果直接使用调用模块,则需要注释掉

如果未注释掉测试代码,此时无论是当前文件,还是其他已经倒入了该模块的文件,在运行的时候都会自动执行函数的测试调用,因此有以下解决办法:

1
2
3
4
5
6
def testA(a,b):
    return a+b

# 测试一下
if __name__ == '__main__':
    print(testA(1,4))

__name__是一个系统变量,是模块的标识符,是每个Python文件的标识符,它的值是:如果__name__运行在自身模块里,那么值就是__main__,如果不是在自身模块运行(即被其他导入模块方式调用时),那么它的值就是被导入的模块名。

例如:在运行模块A时,A中__name__变量的值为__main__,使用模块B去调用模块A并运行时,此时模块A中的__name__变量的值为A,即模块A的名字。

模块定位顺序

当导入一个模块时,Python解释器对模块位置进行搜索,搜索的默认顺序是(由近到远):

  1. 当前目录;
  2. 如果不再当前目录,Python则搜索shell变量PYTHONPATH的每个目录;
  3. 如果都没有,Python会查看默认路径,UNIX下默认路径一般为/usr/local/lib/python

模块搜索路径存储在system模块的sys.path变量中,变量包含当前目录,PYTHONPATH是由安装过程决定的默认目录。

⚠️注意:自己的模块名不要和已有模块名重复,否则导致模块功能无法使用。from 模块名 import 功能名的时候,如果模块中功能名字重复,默认调用到的是最后定义或导入的功能。

  • 体验0:
1
2
3
4
5
import random
class random:
    pass
random = random()
print(random.randint())   # !报错,自己定义的random是没有randint方法的,模块功能无法使用
  • 体验1:

module.py

1
2
3
4
5
def testA(a,b):
    return a+b

def testA(a,b):	# 调用此代码
    return a-b

test.py

1
2
from module import testA
print(testA(1, 4))	# -3
  • 体验2:
1
2
3
4
5
def sleep():
    pass

from time import sleep
sleep()# 此时调用的是上一行代码time模块里的,并不是我们自己定义的。
  • 体验3:
1
2
3
4
import time
print(time) # <module 'time' (built-in)>
time = 1
print(time) # 1

为什么变量能覆盖掉模块功能?因为在Python中数据通过引用传递,time模块名字也对应一个引用,因此后面的数据覆盖前面同名的数据。


__all__

如果在一个模块文件中有__all__变量,它取值为列表数据,当使用from 模块名 import *导入时,只能导入这个列表中的元素,即列表元素携带的功能。

即:all列表规定了在使用from 模块名 import *导入该模块可以调用的功能

  • module代码:
1
2
3
4
5
__all__ = ['testA']
def testA():
    print('A')
def testB():
    print('B')
  • 导入module模块的test代码:
1
2
3
from module import *
testA() # 可以调用
testB() # 报错,无法调用

包是多个有联系模块的统称,包将有联系的模块组织在一起,放到同一个文件夹,并且在这个文件夹下创建一个名字为__init__.py的文件,这个文件控制着包的导入行为,这个文件夹叫包。

制作包的方法

[new] - [Python Package] - 输入包名 - [ok] - 新建功能模块(有联系的模块)

⚠️注意:新建包后,包内部会自动创建__init__.py文件。

体验一下,新建包,在包中建立模块module1和module2

  • module1代码:
1
2
3
print(1)
def info_print():
    print('module1')
  • module2代码:
1
2
3
print(2)
def info_print():
    print('module2')

导入包的方法

  • 方法一:直接使用import 包名.包内模块名
1
2
import mypackage.module1 as m1
m1.info_print()
  • 方法二:在__init__.py文件中添加__all__=[],允许控制使用的模块列表
1
__all__ = ['module1','module2']
1
2
3
from mypackage import *
module1.info_print()
module2.info_print()

因此在包中,__all__变量还可以控制包内允许使用的模块。


总结

  • 导入模块的方法

    • import 模块名
    • from 模块名 import 功能名
    • from 模块名 import *
    • import 模块名 as 别名
    • from 模块名 import 功能名 as 别名

    使用as别名,则只能使用别名来调用,原模块或者功能名称弃用。

  • 制作模块:我们可以把自己项目中需要频繁使用的代码封装到一个py文件中作为一个模块导入到其他需要此模块功能的代码中,该模块的测试最好需要写入到对__name__变量的判断中,如果模块本身运行,则__name__变量的值为__main__,如果模块调用运行则模块中__name__变量的值为模块的名字。

  • 导入包:将关联的模块控制在一起成为一种系统性的功能体系,包下有一个名字为__init__.py的文件,这个文件控制着模块的包的导入行为。导入包的方式有两种:直接import 包名.模块名和在__init__.py文件中写__all__=[]控制模块导入,再使用from mypackage import *方式导入包。

  • __all__ = :限制了导入的模块(写在包中的__init__.py文件)或者导入的功能(写在模块中)