python基础之模块与包
一、面向过程编程(理论)
面向过程编程其实就是类似于设计一条产品流水线。针对问题分解成具体的步骤,然后分步书写。它的好处就是逻辑清晰,流程鲜明,便于理解。它的缺陷就是拓展性差,如果修改功能就需要整体改造,俗称牵一发而动全身。
# 举个例子,假设要现在要做个注册功能,把过程分成三个部分。
# 1.获取用户名;2.按照格式组织;3.把组织好的内容存入文件。
def get():
username = input('用户名:').strip()
password = input('密码:').strip()
return deal(username, password) # 调用函数deal
def deal(username, password):
date = '%s:%s\n' % (username, password)
return save(date) # 调用函数save
def save(date):
with open(r'a.txt', 'a', encoding='utf8') as f:
f.write(date)
get() # 调用函数get
# 如果我们需要改一下,加一个角色功能,就需要修改很多地方:
def get1():
username = input('用户名:').strip()
password = input('密码:').strip()
if len(username) == 0 or password ==0:
print('账号或密码不能为空,请重新输入')
return
else:
dict = {'1': 'idm', '2': 'user'}
print('身份选择选项%s' % dict)
role = input('身份选择:').strip()
if role in dict:
idm = dict.get(role)
return deal1(username, password, idm)
else:
print('输入不合法')
return
def deal1(username, password, idm):
date = '%s:%s:%s\n' % (username, password, idm)
return save1(date) # 调用函数save
def save1(date):
with open(r'a.txt', 'a', encoding='utf8') as f:
f.write(date)
get1() # 调用函数get
二、模块简介
python语言:最早起源于linux运维,被称为胶水语言,调包侠。
学习完模块之后,后续编写大型项目,遇到一些比较复杂的功能,可以先考虑有没有相应的模块可以使用。
1.模块定义:
模块就是一系列功能的结合体,为了提升代码编程效率而存在的。
2.模块三种来源:
内置的:python解释器自带的可以直接导入使用
第三方的:别人写好的发在网上的,需要下载后才能导入使用
自定义:自己写的
3.模块的四种表现形式:
使用python写的代码文件(.py文件)
已被编译为共享库或DLL的C或C++拓展
包好一组模块的包(其实就是文件夹,里面有多个.py文件模块,一般还有一个__init__.py文件)
使用C编写并链接到python解释器的内置模块
三、import...句式
在学习模块的时候,一定要区分执行文件和导入模块。
格式:import md 后缀名不能添加
在执行文件多次导入相同的模块,也只会执行一次。
首次导入模块的内部原理:
运行执行文件会先产生执行文件的全局名称空间
运行...模块文件,产生...模块的全局名称空间
运行...模块的内部代码,把所有产生的名字存在...模块的全局名称空间中
在执行文件的全局名称空间中有一个叫...的模块名指向...模块文件的全局名称空间。
导入模块后,在执行文件可以通过名字点的方式使用模块名称空间中的名字,并且肯定不会产生冲突,因为都是指名道姓的拿,模块名点后面出现的都可以拿。
四、from...import...句式
格式:from 模块名 import 指名道姓的某个名字
在执行文件中导入...的模块的...名字。
内部原理:
先产生执行文件的全局名称空间
再产生模块的全局名称空间
模块中的代码之后后产生的所有名字都存在模块的全局名称空间
在执行文件中有一个名字指向模块全程空间中的名字。
在使用的时候直接使用名字即可,但是如果执行文件的全局名称空间中有一样的名字就会冲突,使用的就变成执行文件的全局名称空间中的名字。
五、导入模块的拓展用法
1.起别名:
既可以给模块起别名也可以给模块中的名字起别名
import 模块名 as 别名
from 模块名 import 名字 as 别名
2.连续导入
import 模块名1,模块名2
适用于多个模板功能相似或者同一系列,否则最好分行导入
import 模块1
import 模块2
from 模块名 import 名字1,名字2
3.通用导入:*
from 模块名 import * # *将模块全局名称空间中所有的名字导入
如有模块文件代码中有出现__all__=['名字','名字'...]代表执行文件导入这个模块只能执行模块中的这些名字。
六、判断文件类型
判断.py文件是作为执行文件还是模块文件
__name__返回__main__的是执行文件,返回模块名的就是模块文件。
需要在执行文件中执行的代码可以用if判断后才能执行调用:
if name == 'main':
函数名()
在pycharm中有个快捷键:main按Tab键就可以直接补全这个if判断。
七、循环导入
多个模块文件互相导入。如果后在导入模块的时候出现了循环导入说明代码设计逻辑有问题。
但是如果出现了,也可以了解一下怎么解决,有两种办法:
1.调换顺序:把彼此导入的命令都放到代码的最后执行
2.用函数包装一下导入的命令,等别的所有需要执行的代码执行的名字加载完成后,再调用执行函数,其实逻辑跟第一种一样,都是最后再执行。
八、循环导入的顺序
在命名自定义模块的时候要求不要与内置模块名冲突!!
导入模块的的查找顺序:
内存》》》内置模块》》》sys.path系统路径(自定义),最后找不到就会报错。
如果在某个自定义模块中找不到,有两种解决办法:
第一种:手动把该模块的所在路径添加到sys.path系统路径中
import sys
sys.path.append(r'该模块的路径')
# sys.path.append(r'D:') 可以直接添加更高级的目录 便于后续导入上级/上上级..的模块
# 注意 导入更高级的模块需要模块所在文件夹有个__init__.py文件 如果没有该文件就创建一个
第二种:使用from ... import...句式 # 后面常用这种,从根目录层层往下剥
from 文件夹名.文件夹名 import 模块名
form 文件夹.模块名 import 名字
from aaa.bbb import 01.py
from aaa.bbb.01.py import name
九、绝对导入与相对导入
在程序中涉及多个文件之间导入模块的情况,一律按照执行文件所在的路径为准。
1、绝对导入:
始终按照执行文件所在的路径为准。
2、相对路径: 句点符(.)
.当前文件夹;
..上一级文件夹
相对路径可以打破‘按照执行文件所在路径为准’的准则,只考虑两个文件之间的位置,只能在模块文件中使用,不能在执行文件中使用。
十、包
1.包是一种通过.模块名把python模块组织起来的方式。包的本质就是一个文件夹,是多个模块功能的结合体,其实包也是一种模块。
2.包首次导入的内部原理:
运行执行文件,产生执行文件的全局名称空间
产生包的全局名称空间,执行包里面的__init__.py文件,产生的名字都存在包的全局名称空间
执行文件的全局名称空间中有一个变量名为包的名字指向包的全局名称空间。
3.其实执行文件导入包就是导入__init__.py文件,需要的导入的其他模块只需要在平级的__init__.py文件中导入就可以在执行文件中使用了。