模块

模块介绍

在Python中,一个py文件就是一个模块,文件名为xxx.py模块名则是xxx,导入模块可以引用模块中已经写好的功能。如果把开发程序比喻成制造一台电脑,编写模块就像是在制造电脑的零部件,准备好零部件后,剩下的工作就是按照逻辑把它们组装到一起。

将程序模块化会使得程序的组织结构清晰,维护起来更加方便。比起直接开发一个完整的程序,单独开发一个小的模块也会更加简单,并且程序中的模块与电脑中的零部件稍微不同的是:程序中的模块可以被重复使用。所以总结下来,使用模块既保证了代码的重用性,又增强了程序的结构性和可维护性。另外除了自定义模块外,我们还可以导入使用内置或第三方模块提供的现成功能,这种“拿来主义”极大地提高了程序员的开发效率。

作为一名python程序员将来接收到某个业务需求的时候 不要上来就想着自己写 先看看有没有相应的模块已经实现

模块分类

内置模块

解释器自带的 直接就可以使用的模块

例子

import time
time.sleep(3)

自定义模块

登录功能
is_login = {
'username':''
}
def login_auth(func_name):
def inner(*args, **kwargs):
# 先判断全局字典中username键中是否有值,如果有说明用户已经登录成功 无需反复校验
if is_login.get('username'):
res = func_name(*args, **kwargs)
return res
username = input('username>>>:').strip()
password = input('password>>>:').strip()
if username == 'lele' and password == '123':
# 记录用户登录成功状态
is_login['username'] = username
res = func_name(*args, **kwargs)
return res
else:
print('用户名或密码错误 ')
return inner

@login_auth
def register():
print('注册功能')
@login_auth
def login():
print('登录功能')
@login_auth
def transfer():
print('转账功能')
@login_auth
def withdraw():
print('提现功能')

register()
login()
transfer()
withdraw()

第三方模块

别人写的模块 存在于网络上 使用之前需要提前下载

白嫖

模块的表现形式

1.py文件(py文件也可以称之为是模块文件)

2.含有多个py文件的文件夹(按照模块功能的不同划分不同的文件夹存储)

3.已被编译为共享库或DLL的c或C++扩展

4.使用C编写并链接到python解释器的内置模块

导入模块的两种句式

"""
补充说明
以后真正的项目中 所有的py文件名称都是英文
没有所谓的编号和中文
eg:
错误的 01.变量的使用
正确的 test01.py
学习模块的时候 模块文件的名称就得用英文

py文件被当做模块导入的时候不需要考虑后缀
"""
导入模块的句式1 import句式
import md
"""
import md
执行文件是 02 模块的导入句式.py
被导入文件是 md.py

1.会产生执行文件的名称空间
2.产生被导入文件的名称空间并运行该文件内所有的代码 存储名字
3.在执行文件中会获取一个模块的名字 通过该名字点的方式就可以使用到被导入文件名称空间中的名字

补充说明
同一个程序反复导入相同的模块 导入语句只会执行一次
import md 有效
import md 无效
import md 无效
"""
# money = 10
# print(md.money)
# print(money)


# def read1():
# print('我是执行文件里面的read函数')
# md.read2()

# money = 1000
# md.change()
# print(money)
# print(md.money)

导入模块的句式2 from...import...句式
# from md import money # 指名道姓的导入
# print(money) # 999
# money = '嘿嘿嘿'
# print(money) # 嘿嘿嘿
# print(read1)
# print(md.read1())

from md import money, read1
read1()
"""
1.创建执行文件的名称空间
2.创建被导入文件的名称空间
3.执行被导入文件中的代码 将产生的名字存储到被导入文件的名称空间中
4.在执行文件中获取到指定的名字 指向被导入文件的名称空间
"""

两种导入句式的优缺点

mport md
优点:通过md点的方式可以使用到模块内所有的名字 并且不会冲突
缺点:md什么都可以点 有时候并不想让所有的名字都能被使用
from md import money, read1
优点:指名道姓的使用指定的名字 并且不需要加模块名前缀
缺点:名字及其容易产生冲突(绑定关系被修改)

模块

 其他导入语法(as)

通过as给导入的模块气外号

import foo as f #为导入的模块foo在当前位置起别名f,以后再使用时就用这个别名f
f.x
f.get()

还可以为导入的一个名字起别名

from foo import get as get_x
get_x()

通常在被导入的名字过长时采用起别名的方式来精简代码,另外为被导入的名字起别名可以很好地避免与当前名字发生冲突,还有很重要的一点就是:可以保持调用方式的一致性,例如我们有两个模块json和pickle同时实现了load方法,作用是从一个打开的文件中解析出结构化的数据,但解析的格式不同,可以用下述代码有选择性地加载不同的模块

if data_format == 'json':
import json as serialize #如果数据格式是json,那么导入json模块并命名为serialize
elif data_format == 'pickle':
import pickle as serialize #如果数据格式是pickle,那么导入pickle模块并命名为serialize

data=serialize.load(fn) #最终调用的方式是一致的

模块

循环导入问题

循环导入问题指的是在一个模块加载/导入的过程中导入另外一个模块,而在另外一个模块中又返回来导入第一个模块中的名字,由于第一个模块尚未加载完毕,所以引用失败、抛出异常,究其根源就是在python中,同一个模块只会在第一次导入时执行其内部代码,再次导入该模块时,即便是该模块尚未完全加载完毕也不会去重复执行内部代码

我们以下述文件为例,来详细分析循环/嵌套导入出现异常的原因以及解决的方案

模块

解决方案:

导入语句放到最后,保证在导入时,所有名字都已经加载过
导入语句放到函数中,只有在调用函数时才会执行其内部代码

注意:循环导入问题大多数情况是因为程序设计失误导致,上述解决方案也只是在烂设计之上的无奈之举,在我们的程序中应该尽量避免出现循环/嵌套导入,如果多个模块确实都需要共享某些数据,可以将共享的数据集中存放到某一个地方,然后进行导入

绝对路径与相对路径

当执行文件与导入的文件不在同一个目录下 可能产生导入失败的情况

模块

1.解决方式1

利用form...import...局式

     基于执行文件所在的路径一层层查找模块文件的所在路径即可

from aaa import md

form ​​aaa.bbb.md​​ import money

2.解决方式2

        利用sys.path系统路径

模块

模块的查找顺序是:

1.先从内存中查找

2.内置中查找

3.执行文件所在的sys.path中查找

启动脚本

1.当__name__所在的文件是执行文件的时候结果是__main__

2.当__name__所在的文件是被导入文件的时候(模板) 结果是模块名

if  name  == 'name':

只有是执行文件的时候才会执行的代码

编写一个规范的模块

在编写py文件时,需要时刻提醒自己,该文件既是给自己用的,也有可能会被其他人使用,因而代码的可读性与易维护性显得十分重要,为此我们在编写一个模块时最好按照统一的规范去编写,如下

#!/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() #在被当做脚本执行时,执行此处的代码

模块

发表评论

相关文章