面向过程编程,模块的使用,循环导入问题,模块导入顺序

面向过程编程

WechatIMG593

强调:

面向过程编程绝对不是用函数编程这么简单,面向过程是一种编程思路、思想,而编程思路是不依赖于具体的语言或语法的。言外之意是即使我们不依赖于函数,也可以基于面向过程的思想编写程序

定义:

核心是 “过程” 二字,过程就是解决问题的步骤,即先干什么、再干什么、后干什么。所以基于该思想编写程序就好比设计一条一条的产品流水线

  • 优点:复杂的问题流程化,进而就简单化(逻辑清晰,流程鲜明,便于理解)
  • 缺点:一旦要修改功能,那么需要整体改造(牵一发而动全身,扩展性差)

应用:

# 用户注册功能
'''
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()



模块

download-1_gaitubao_270x266

模块简介

python语言

最早起源于linux运维、胶水语言、调包侠(贬义词 >>> 褒义词)

什么是模块

  • 模块就是一系列功能的集合体

为何要用模块

  • 1、(自带的模块,第三方模块)--->拿来主义,极大的提升开发效率
  • 2、自定义模块--->是为了解决代码冗余问题

模块有三种来源

  • 1、内置的模块(①直接在python解释器内部的   ②标准库:下载python解释器就有的py文件)

  • 2、第三方模块(下载第三方库:pip3 install requests)

  • 3、自定义的模块(自己写的)

模块的四种表现形式

  • 1、使用python编写的代码,一个py文件就是一个模块,文件名叫test.py,模块名叫test

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

  • 2、一个包含有_init_.py文件的文件夹称之为包,包其实就是多个py文件(模块)的集合

  • 4、使用C编写并连接到python解释器的内置模块

mokani_gaitubao_309x255


模块的使用

  • 模块都是用来被导入使用的,而不是直接运行

以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...的方式有好处也有坏处
    优点:使用起来方便了
    缺点:容易与当前执行文件的名称空间名字冲突
  
"""
学习完模块之后,以后在编写大型项目的时候 
遇到一些比较复杂的功能可以先考虑是否有相应的模块可以调用
"""

mokuai_gaitubao_241x241

导入模块扩展用法

# 其他用法
# 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判断"""

xunhuanz_gaitubao_495x452_gaitubao_290x266

模块循环导入问题

模块循环导入抛出异常的根本原因是由于在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()

"""仅供参考,以后开发过程中最好不要出现循环导入"""

在我们的项目中应该尽量避免出现循环导入的现象,如果出现多个模块都需要共享的数据,可以将共享的数据集中存放到某一个地方


zhuji_gaitubao_239x239

模块导入的顺序

  • 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
posted @ 2021-01-05 16:39  山风有耳  阅读(160)  评论(0编辑  收藏  举报