1.python中的模块
python中的模块本质上就是一个py文件,我们可以使用 import 文件名 的方式导入文件,当导入文件后,我们就可以使用此文件中包含的变量和函数。
python中的模块分为3种
1.内置模块:直接导入就可以使用的模块,例如:time,sys,random等模块;
2.扩展模块:可以使用 pip install 进行安装的第三方模块;
3.自定义模块:自己写的模块。
对模块的命名规则与对变量的命名规则相同:由数字、字母、下划线组成且以字母或下划线开头;
模块的导入规则:
1.应当在文件开始就导入
2.先导入内置模块
3.再导入扩展模块 - 可以使用 pip 安装
4.自己写的自定义模块
2.模块的相关问题
1.模块的重复导入问题:
我们都知道,在同一py文件中多次导入相同的模块,最终起作用的其实只有第一次导入,其原因如下:
import sys
print(sys.modules)
print(sys.modules.keys())
# print(sys.path)
执行上面代码,我们可以看到如下的输出:
我们可以看到,在此py文件中导入的模块其模块相关信息都会保存在这个字典中,那么当我们导入模块时,若模块名字已经存在于此字典中则不再导入相同模块,只有模块名不存在时才会导入模块,因此若多次导入相同的模块,只有第一次导入时才生效。
2.自定义模块时pycharm会报错:
当我们新建一个 demo.py 文件,并在其他文件中 import demo 时,会看到pycharm飘红:
此时并不是说我们的代码出现错误,因为代码是可以正确运行的 ,那么出现这种现象的原因如下:
import sys
print(sys.path)
执行上面代码,我们会看到一个列表,列表中的元素是不同的路径:
pycharm 编辑器在寻找一个文件时,默认会以 当前在pycharm的打开的工程目录为根目录,在此目录下边寻找需要导入的模块对应的 py 文件;
1.若找到了则不会报错还能自动补全;
2.若没找到,会报错,但是当我们运行代码时,解释器是可以解释的,代码不会出错;
当我们自定义的模块py文件若在 sys.path 中的路径下能找到,代码就可以执行。
3.当我们在导入一个模块时,发生了哪些事?
在对一个模块进行导入时,发生了以下流程:
1.找到模块 - 先从 sys.modules 里查看模块是否已经被导入,
- 若被导入则不再重复导入,
- 若没有被导入,则依据 sys.path 中的路径寻找所要导入的模块;
2.找到模块对应的 py 文件后,创建这个模块的命令空间;
3.执行文件,将文件中的名字都放进命名空间里 - 与其他文件的命名空间相隔离.
3.模块的使用
1.给模块起别名:将模块重命名
格式:import 模块名 as 模块别名
给模块起别名后,就可以通过 模块别名.函数 的方式来调用模块中的方法,例如:
import time as t # 给time模块起别名为 t --> t == time
print(t.time()) # t.time() == time.time()
2.同时导入多个模块
格式:import 模块1, 模块2 ...
说明:不推荐这样的导入方式,需要导入多个模块时,最好多行导入
import time,sys,os # 一次导入 time,sys,os 模块
print(time.time())
print(sys.modules.keys())
print(os.name)
3.单独从某个模块中只导入一个 方法或变量
格式:from 模块 import 方法|变量
注意:若是导入一个变量,则此变量成为 全局变量
from time import time
print(time()) # 直接调用导入的方法即可
4.从一个模块中导入多个方法或变量
格式:from 模块 import 变量1,变量2,方法1...
from time import time,strftime,localtime
print(time())
print(strftime('%F %T',localtime()))
输出结果如下:
5.对导入的变量名进行重命名
格式:from 模块名 import 变量名 as 重命名的变量名
例如:
from time import sleep as s
s(1) # == sleep(1) == time.sleep(1)
6.from 模块 import *
当模块中不含有 __all__ 参数时, from 模块 import * 效果等价于 import 模块
例如:from time import * == import time
区别在于函数的调用方式:
from time import *
print(time()) # 可以直接调用
import time
print(time.time()) # 通过 time.time() 调用
当模块中含有 __all__ 参数时,from import * 只能导入 __all__ 中存在的名字; 但是 import 模块 仍能导入模块所有的名字.
例如:demo.py 文件内容如下
__all__ = ['money']
money = 100
def read():
print('money: ',money)
导入模块调用read()
则在执行代码时会出现如下错误:
当使用 import 时:
import demo
print(demo.money)
demo.read()
代码正常执行:
注意:__all__ = [] # 必须是一个列表,列表中的元素必须是一个字符串,字符串必须是py文件中已经存在的函数或变量的名字
7.导入模块或变量名复用问题
是我们自己在文件中写的 函数 或 变量 的函数名或变量名 与 import 导入的模块中的函数名或变量名相同,那么默认优先使用本地文件中的名字,import 的会被覆盖;
例如:
from time import sleep
sleep = 100
print(sleep)
print(callable(sleep)) # 判断 sleep 是否可调用
输出结果如下:
4.自定义模块的使用
我们已经知道,自定义模块其实就是一个我们自己写的py文件,那么,我们写一个 demo,py 内容如下:
print('This is demo module.')
money = 100
def read():
print('money: ',money)
在另一个py文件导入如下:
执行结果如下:
我们可以看到,demo.py中的 print 语句直接被执行了,read() 函数使用 demo.read() 方式被调用。
5.一些说明
1.导入变量重新赋值问题
demo.py 文件内容如下:
print('This is demo module.')
money = 100
money1 = []
def read():
print('money: ',money)
print('money1: ',money1)
执行如下代码:
from demo import money,money1,read
money = 200
money1.append('money1')
read() # 在对money 和 money1 的值进行修改后再调用read()函数
输出结果如下:
说明如下:
This is demo module. # print() 输出
money: 100 # 虽然对 money 的值进行了修改,但是read到的还是demo.py文件中的money - 就近原则
# money 是不可变数据类型,当重新赋值后,其地址就改变了,就近原则找到的money还是demo.py中的值
money1: ['money1'] # 列表是可变数据类型,就算是进行了增删改查,内存地址也不变.
2.__name__ 参数使用
我们可以看到,当我们导入 demo 模块时,其中的 print() 语句就会自动被执行,那么,如果我们需要:只在执行 demo.py 文件的时候才执行 print ,而当 demo.py 是作为一个模块被导入时不要执行 print 语句,就需要使用 __name__ 参数,
__name_ 参数的性质如下:
当在本文件中使用时:此参数的值是__main__;
当模块被调用后,执行别的py文件此参数的返回值是模块名;
在 demo.py 文件中输出此参数:
print('This is demo module.')
money = 100
money1 = []
def read():
print('money: ',money)
print('money1: ',money1)
print(__name__) # 直接执行 demo.py ,输出是 __main__
输出结果如下:
当demo模块被导入,输出结果如下:
import demo
所以我们可以使用它的这一性质来实现以上需求:
在 demo.py 文件中判断:
money = 100
money1 = []
def read():
print('money: ',money)
print('money1: ',money1)
if __name__ == '__main__':
print('This is demo module.')
那么在导入demo时,运行就不会输出print语句,而在执行demo.py文件时才有输出。