14. 模块与导入模块

2021/11/5 23:16:21

本文主要是介绍14. 模块与导入模块,对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!

模块

模块介绍

就是一系功能的集合体,分为三大类,一种是内置模块,一种是自定义模块(自己写的),一种是第三方模块(别人写的)

本质上一个python文件本身就是一个模块,文件名是m.py,模块名是m

模块分为四种形式:

  1. python写的.py文件就是一个模块
  2. 已经被编译为共享库或DLL的c或者c++拓展
  3. 把一些列模块组织到一起的文件夹
  4. 使用c编写并链接到Python解释器的内置模块(文件夹下面必须有一个__init__.py文件,该文件夹被称为包)

模块的优点:

  1. 内置与第三方模块不需要定义,直接可以使用,这种拿来主义极大的提高了开发的效率
  2. 自定义模块能将常用的函数(功能)提取出来放在一起,方便调用和共享,减少了代码冗余,是代码结构更加清晰

首次导入模块发生的三件事

  1. 执行a(假设是a.py文件)模块里面的代码

  2. 产生a.py文件的名称空间,将a.py代码执行过程中的产生的名称丢到名称空间中

  3. 在当前文件中产生一个名称a(可以理解为变量,但是不是变量a),该名称指向2中产生的名称空间

    之后的导入,不会再重复上述的内容,而是直接引用首次导入产生的a.py的名称空间(模块只在第一次导入的时候执行,之后的导入不会再执行,而是直接使用)

import导入模块

  1. 直接导入:import xxx
### 1. 根据名称直接访问,指名道姓,这种方式不会和当前文件中的变量产生冲突(name和a.name是不一样的)
# 无论是查看还是修改都是原文件上的操作,与调用位置无关
import a
name='张三'
print(a.name)  # 取a模块的name变量,不是'张三'
print(a.func)  # 取a模块中的func函数
### 2. 导入多个模块
import a
import b
# 上面和下面的两种方式是等价的,但是下面的方法不推荐使用,主要是不清晰
import a,b
### 3. 起别名:主要是模块名字太复杂的时候使用
import ahsjdadhajsdajdglfj as b
b.get
### 4. 模块是第一类对象
### 5. 自定义模块命名的时候应该是全小写加下划线的方式
### 6. 函数内也可以使用模块
def func():
    import a
    pass
  1. from 文件名 import 变量/函数

    import 模块名虽然解决了名称冲突的问题,但是在使用时必须加上前缀,比较麻烦,所以有了下面的方法

    from a import func
    from a import func1
    from a import func2
    # 两种方式,还是推荐上面的写法
    from a import func,func1,func2
    ## 导入全部的内容
    from a import *  # 不推荐使用
    

    这种方式有一个问题,就是当前文件和模块中的文件有相同名称的变量/函数时,Python解释器会优先调用当前文件的变量/函数

    控制导入的名称(all属性)

    __all__属性在被导入的模块中会显示所有模块中的名称,包含变量和函数的,形成一个列表,实际上在用*进行导入的时候,就是在该列表中进行检索,当然,可以对all属性进行设置,控制被导入的名称这样被导入的时候,只能使用列表中的名称

    __all__=[a,b,func1,func2]
    

python文件的两种用途

  1. 被当做程序直接运行
  2. 被当作模块运行

每一个python文件都有一个属性name,能够显示文件的用途

# 1. 当文件被当做程序直接运行的时候
__name__='__main__'
# 2. 当文件被当做模块运行时
__name__='文件名,也就是模块名'
### 所以可以在文件中添加判断,指定文件的用途
if __name__=='__main__':
    print('文件被当做程序运行')
else:
    print('文件被当做模块运行')

循环导入问题

就是在a文件中导入b模块,在b文件中导入a模块

# 举例说明一下
# a文件
from b import b
a=111
# b文件
from a import a
b=222
# 过程:运行a文件,执行到from b import b,再去b文件找b,运行到from a import a,再去a文件找a,此时模块a已经开辟了名称空间了,所以直接找a变量,但是a变量还没赋值(代码还没执行到那里),报错

# 解决方案1(不推荐)
# a文件
a=111
from b import b
# b文件
b=222
from a import a
# 解决方案2(不到万不得已不要使用)
# a文件
def func1():
	from b import b
a=111
# b文件
def func1():
	from a import a
b=222
### 这样文件加载的时候不会执行函数内的代码,只有在调用函数的时候才会导入,此时的b已经加载完成了

模块查找优先级

  1. 内存中(包括内置模块)(sys.modules查看已经加载到内存中的模块,考虑到性能的原因,每个模块只被导入一次,放入字典sys.module中,如果改变了模块的内容,必须重启程序,python不支持重新加载或卸载之前导入的模块)
  2. 硬盘中(文件夹中)是按照sys.path中的文件夹顺序进行查找
# 从硬盘中查找
import sys
print(sys.path)  # 结果是一个列表,第一个元素是当前文件夹的路径,第二个元素是项目的路径(pycharm安装时添加的,不重要),第三个元素是

# sys.modules查看内存中的模块:返回一个字典,里面是加载到内存中的模块

sys.path的应用

sys.path.append(r'模块路径')

当找不到模块存在的路径的时候,可以使用这种方法将文件路径添加到路径中(这是临时添加,文件关闭的时候就会取消)

编写规范的模块

#!/usr/bin/env python # 通常只在类unix环境有效,作用是可以使用脚本名来执行,而无需直接调用解释器

"The module is used to..." # 模块的文档描述

import sys # 导入模块
x=1 # 定义全局变量,如果非必须,则最好使用局部变量,这样可以提高代码的易维护性,并且可以节省内存提高性能
class Foo: # 定义类,并写好类的注释
    'Class Foo is used to...'
    pass
def test(): # 定义函数,并写好函数的注释
    'Function test is used to…'
    pass
if __name__ == '__main__': # 主程序
    test() # 在被当做脚本执行时,执行此处的代码

​ 顺序不固定,但是这样的顺序更加的清晰



这篇关于14. 模块与导入模块的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!


扫一扫关注最新编程教程