Python学习之Part26.模块的概念

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文件时才有输出。

发布了72 篇原创文章 · 获赞 7 · 访问量 1万+

猜你喜欢

转载自blog.csdn.net/weixin_41781946/article/details/104425674