面向过程编程、模块的使用、循环导入问题、模块导入顺序
面向过程编程
强调:
面向过程编程绝对不是用函数编程这么简单,面向过程是一种编程思路、思想,而编程思路是不依赖于具体的语言或语法的。言外之意是即使我们不依赖于函数,也可以基于面向过程的思想编写程序
定义:
核心是 “过程” 二字,过程就是解决问题的步骤,即先干什么、再干什么、后干什么。所以基于该思想编写程序就好比设计一条一条的产品流水线
- 优点:复杂的问题流程化,进而就简单化(逻辑清晰,流程鲜明,便于理解)
- 缺点:一旦要修改功能,那么需要整体改造(牵一发而动全身,扩展性差)
应用:
# 用户注册功能
'''
1.获取用户名和密码
2.组织成固定的格式
3.文件操作写入文件
'''
def get_info():
username = input('username>>>:').strip()
password = input('password>>>:').strip()
if len(username) == 0 or len(password) == 0:
print('用户名或密码不能为空')
return
user_idf = {
'1':'admin',
'2':'user',
}
print(user_idf)
choice = input('请选择您的身份>>>:').strip()
if choice in user_idf:
id = user_idf.get(choice)
return deal_data(username, password,id)
else:
print('输入不合法')
return
def deal_data(username,password,id):
data = '%s|%s|%s\n'%(username,password,id)
return save_data(data)
def save_data(data):
with open(r'userinfo','a',encoding='utf8') as f:
f.write(data)
print('注册成功')
get_info()
模块
模块简介
python语言
最早起源于linux运维、胶水语言、调包侠(贬义词 >>> 褒义词)
什么是模块
-
模块就是一系列功能的集合体
-
为何要用模块
-
1、(自带的模块,第三方模块)--->拿来主义,极大的提升开发效率
-
2、自定义模块--->是为了解决代码冗余问题
-
-
模块有三种来源
-
1、内置的模块(①直接在python解释器内部的 ②标准库:下载python解释器就有的py文件)
-
2、第三方模块(下载第三方库:pip3 install requests)
-
3、自定义的模块(自己写的)
-
-
模块的四种表现形式
-
1、使用python编写的代码,一个
py
文件就是一个模块,文件名叫test.py
,模块名叫test -
2、已被编译为共享库或
DLL
的C或C++扩展 -
3、一个包含有
_init_.py
文件的文件夹称之为包,包其实就是多个py文件(模块)的集合 -
4、使用
C
编写并连接到python解释器的内置模块
-
模块的使用
模块都是用来被导入使用的,而不是直接运行
以md.py为例来介绍模块的使用:文件名md.py,模块名md
# md.py 模块文件
print('from the md.py')
money = 1000
def read1():
print('md', money)
def read2():
print('md模块')
read1()
def change():
global money
money = 0
import 句式
# start.py 文件
# 导入md.py文件模块
import md # 后面跟模块名一定不要加.py,该模块名指向的是md.py的名称空间
import md # 多次导入相同模块,只会执行一次
import md
# ps: 后续的导入直接引用首次导入成功的,不会重复执行md.py,不会重复创建名称空间
'''
首次导入模块发生的事情
1、运行导入文件(start.py)产生该文件的全局名称空间
2、运行md.py,产生md.py全局名称空间,将md.py运行过程中产生的名字全部存档于md.py名称空间
3、在导入文件名称空间产生一个md的名字指向md.py全局名称空间
import句式导入模块之后
通过模块名点的方式就可以使用到模块中所有的名字,并且肯定不会产生冲突(指名道姓)
'''
print(md.money) # 1000 指名道姓向md.py调money
md.read1() # md 1000
md.read2() # md模块
md.change() # md 1000
money = 2000
print(money) # 2000 没加前缀就是向当前名称空间调用
print(md.money) # 1000 加前缀拿到的就是md.py名称空间中money的值
def read1():
print('xxx')
# 加md.前缀,名字不会与当前名称空间名字冲突,每次调用都需要加前缀
md.read1() # md 1000 名称空间的关系是在定义阶段确立的与调用无关
from...import... 句式
# run.py 文件
# 导入md.py文件模块,多次导入相同模块,也只会执行一次
from md import money
from md import read1
# ps: 后续的导入直接引用首次导入的成功,不会重复执行md.py、不会重复创建名称空间
'''
首次导入模块发生的事情
1、运行导入文件(run.py)产生该文件的全局名称空间
2、产生md.py全局名称空间 运行md文件内代码 将产生的名字全部存档于md.py名称空间
2、在当前执行文件名称空间中得到一个名字money,该名字是指向模块的名称空间中的那个money的值
from...import...指名道姓的导入某个名字
在使用的时候直接写名字即可,但是当当前名称空间有相同名字的时候
就会产生冲突,使用的就变成了当前名称空间
'''
money = 2000
print(money) # 2000 money与当前名称空间名字冲突,会互相覆盖
read1() # md1000 先确定read1()来自于哪,以来的地方为准找作用域关系
def read1():
print('董小姐',money)
read1() # 董小姐 2000 此时read1()找的是当前名称空间
'''
导入规范
通常情况下所有的导入语句都应该写在文件的开头,然后分为三部分:
第一部分:先导入自带的模块
第二部分:导入第三方
第三部分:导入自定义的
'''
from import与import的对比
唯一的区别就是:使用from...import...则是将md中的名字直接导入到当前的名称空间中
所以在当前名称空间中,直接使用名字就可以了,无需加前缀:md.
import
优点:加前缀不会与当前执行文件的名称空间名字冲突
缺点:加前缀使用起来麻烦
from...import...的方式有好处也有坏处
优点:使用起来方便了
缺点:容易与当前执行文件的名称空间名字冲突
"""
学习完模块之后,以后在编写大型项目的时候
遇到一些比较复杂的功能可以先考虑是否有相应的模块可以调用
"""
导入模块扩展用法
# 其他用法
# 1.起别名
from md import money as m, read1 as r1, read2 as r2,change # 也支持as,为模块起别名
print(m) # 1000
r1() # md 1000
# 2.连续导入
from md import money, read1, read2, change # 在一行一次导入多个名字(模块)
'''
可以连续导入多个模块,但是只有当多个模块功能相似或者属于同一个系列
如果功能不同并且不属于一个系列,那么推荐分行导入
'''
# 3.通用导入 from...import*
from md import * # 将模块中所有不是以下划线开头的名字都导入到当前位置
print(money)
print(read1)
print(read2)
print(change)
'''
大部分情况下我们的python程序不应该使用这种导入方式,因为*你不知道你导入什么名字,很有
可能会覆盖掉你之前已经定义的名字。而且可读性极其的差,在交互式环境中导入时没有问题。
__all__ = ['money', 'read1'] # 在被导入的模块文件中可以使用__all__指定可以被导入使用的名字
'''
判断文件类型
编写好的一个python文件可以有两种用途:
-
1、脚本(执行文件),一个文件就是整个程序,用来被执行
-
2、模块,文件中存放着一堆功能,用来被导入使用
# 判断py文件是作为模块文件,还是执行文件
python为我们内置了全局变量__name__
当文件被当做脚本执行时:__name__ 等于 '__main__'
当文件被当做模块导入时:__name__等于模块名
# 作用:用来控制.py文件在不同的应用场景下执行不同的逻辑
if __name__ == '__main__': # 以后再启动文件入口这样写
read1()
"""在pycharm中可以直接敲 main按tab键即可自动补全if判断"""
模块循环导入问题
解释:
模块循环导入抛出异常的根本原因是由于在python中模块被导入一次之后,就不会重新导入,只会在第一次导入时执行模块内代码。以后我们在导入模块的时候如果出现了循环导入的情况,说明你程序设计的不合理
# m1.py
print('正在导入m1')
from m2 import y # 首次导入m2
x = 'm1'
# m2.py
print('正在导入m2')
from m1 import x # 第二次导入m1
y = 'm2'
# cycle_imp.py
import m1
"""
运行cycle_imp.py后出现的报错信息:
ImportError: cannot import name 'x' from partially initialized module 'm1' (most likely due to a circular import)
导入错误:无法从部分初始化的模块“m1”中导入名称“x”(很可能是由于循环导入)
"""
上述错误解决方法:(一错再错,朝着错误的方向改)
'''
1.调换顺序
将彼此导入的句式放在代码的最后
'''
# m1.py
print('正在导入m1')
x = 'm1'
from m2 import y # 首次导入m2
# m2.py
print('正在导入m2')
y = 'm2'
from m1 import x # 第二次导入m1
'''
2.函数形式
将导入的句式放入函数体代码 等待所有的名字加载完毕之后再调用
'''
# m1.py
print('正在导入m1')
x = 'm1'
def index():
from m2 import y # 首次导入m2
print(y)
index()
# m2.py
print('正在导入m2')
y = 'm2'
def index():
from m1 import x # 第二次导入m1
print(x)
index()
"""仅供参考,以后开发过程中最好不要出现循环导入"""
在我们的项目中应该尽量避免出现循环导入的现象,如果出现多个模块都需要共享的数据,可以将共享的数据集中存放到某一个地方
模块导入的顺序
-
1、内存中已经导入好的
-
2、内置模块中查找
-
3、sys.path系统路径查找
# 查找顺序:内存---》内置---》sys.path 都没有则保报错
'''
1.内存:在第一次导入某个模块时(比如md),会先检查该模块是否已经被加载到内存中
(当前执行文件的名称空间对应的内存),如果有则直接引用
ps:python解释器在启动时会自动加载一些模块到内存中,可以使用sys.modules查看
'''
# m1.py
def index():
print('from m1 index')
# test.py
import m1 # 导入m1模块
import time
m1.index() # from m1 index 可以正常执行
'''
在五秒内删除m1并执行当前模块仍能调取m1
过完5秒再执行就出现报错,说明优先从内存找
'''
time.sleep(5)
m1.index()
'''2.内置:如果内存没有,python解释器则会查找同名的内置模块'''
import time,os
print(time) # <module 'time' (built-in)>
print(os) # <module 'os' from 'D:\\Python36\\lib\\os.py'>
'''3.sys.path:如果内置还没有找到就从sys.path给出的目录列表中依次寻找md.py文件'''
import sys
print(sys.path)
import m1
m1.index() # 找不到
import aaa.m1 as m
aaa.m1.index() # 报错,取了别名之前的名字就不能使用了
m.index() # from m1 index
# 需要特别注意的是:以后在给py文件命名的时候尽量不要与内置模块名冲突
# 当某个自定义模块查找不到的时候解决方案
'''
方案1.自己手动将该模块所在的路径添加到sys.path中
在初始化后,python程序可以修改sys.path,路径放到前面的优先于标准库被加载
'''
import sys
print(sys.path) # 结果中第一个元素永远是当前执行文件所在的路径
sys.path.append(r'D:\py20\day18') # windows下的路径不加r开头,会语法错误
import m1
m1.index() # from m1 index
'''
方案2.from...import...句式
from 文件夹名称.文件夹名称 import 模块名
from 文件夹名称.模块名称 import 名字
'''
from aaa.bbb import m1
m1.index() # from m1 index
from aaa.bbb.m1 import index
index() # from m1 index