zoukankan      html  css  js  c++  java
  • 🍖模块介绍

    一.模块介绍

    1.什么是模块

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

    2.模块的四种通用类别

    • 使用 Python 写的 .py 文件, 例 : 文件名 test.py, 模块名为 test
    • 盛放有多个 py 文件的文件夹也是一个功能的集合体, 相当于一种超级模块, 称之为
    • 已被编译为共享库或DLL的C或C++扩展
    • 使用 C 编写并链接到 Python 解释器的内置模块

    3.模块的三种来源

    • 自带的模块

      1. 内置模块
      2. 标准库
    • 第三方模块

      • 可以通过 pip 工具下载的别人写的一些优秀的模块
      • 例 : pip3 install requests
    • 自定义模块

    4.为何要使用模块

    • 使用自带或第三方模块 : 写好的功能拿来就用, 提升开发效率
    • 使用自定义模块 : 减少代码冗余, 让程序的组织结构更清晰

    5.导入模块规范

    1. Python内置模块
    2. 第三方模块
    3. 自定义模块

    4.模块导入示例

    ⛅"spam.py" 文件
    print("i am spam")  # 只要执行此文件就会打印 "i am spam"
    
    x = 1000
    def aaa():
        print("i am spam.aaa")
    
    def bbb():
        print("i am spam.bbb")
        aaa()
    
    def change():
        global x
        x = 0
    
    ⛅"run.py" 执行文件
    import spam   # 导入模块先执行一次被导入模块文件, 会打印 "i am spam"
    import spam   # 之后的导入都是直接引用第一次导入的结果, 不会重复执行文件
    import spam
    
    x = 2000      # 当前执行文件下的变量 "x"
    spam.aaa()    # 使用模块的 "aaa" 功能, 打印 "i am spam.aaa"
    spam.bbb()    # 使用模块的 "bbb" 功能, 打印 "i am spam.bbb" 并调用模块的 "aaa" 打印 "i am spam.aaa"
    spam.change() # 使用了模块的 "change" 功能,改变的是定义阶段就规定好了的去 "spam" 名称空间找变量名 "x"
    print(x)      # 所以这里打印的还是 "run.py" 的 "x" : 2000
    print(spam.x) # 而 "spam.py" 里面的 "x" : 0
    

    二.模块使用之 import

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

    • 创建一个模块的名称空间
    • 执行模块对应文件, 将执行文件产生的名字存放于这个名称空间中
    • 在当前执行文件中拿到一个模块名, 该模块名指向被导入模块的名称空间

    模块导入

    2.import 的使用

    • 强调 : 只有首次导入才会执行被导入模块文件, 并创建一个名称空间
    • 之后的导入都是直接引用首次导入的结果
    • 模块中功能的执行始终以模块自己的名称空间为准(名称空间的嵌套关系是在定义阶段就确定的,与调用位置无关)
    import spam
    import spam
    import spam
    import spam
    import spam
    
    print(spam)  # <module 'spam' from 'F:\\Pycharm File\\spam.py'>
    spam.aaa()
    

    3.import 的优缺点

    • 优点 : 指名道姓的引用某个模块的名字, 不会有冲突
    • 缺点 : 需要加前缀, 引用次数多的时候就比较麻烦

    4.为模块起别名

    • 名字比较长的情况下
    import spam as ss
    import songhaixing as shawn
    

    5.导入多个模块

    ⛅不推荐使用
    import os, sys, time
    
    ⛅推荐使用(清晰明了)
    import os
    import sys
    import time
    

    三.模块使用之 from...import...

    1.首次导入模块发生三件事

    • 创建一个模块的名称空间
    • 执行对应文件, 将产生的名字存放于刚创建的名称空间中 (前两个步骤与 import 一样)
    • 在当前名称空间中拿到模块中的名字, 可以直接使用, 不用加任何前缀

    2.from...import 的使用

    • import一样,执行模块中的功能,始终以模块的名称空间为准(名称空间的嵌套关系是在定义阶段就确定的,与调用位置无关)
    from spam import aaa, bbb, change
    
    print(aaa)
    aaa()
    bbb()       #可以直接调用
    change()    #不需要调用名字
    

    3.from...import 的优缺点

    • 优点 : 不用加前缀, 直接引用模块中的名字, 代码更精简
    • 缺点 : 容易与当前执行文件名称空间中的重复名字发生冲突

    4.为模块取别名

    from spam import change as ch
    
    print(ch)
    ch()
    

    5.导入多个模块功能

    from...improt *  # "*" 代表所有
    
    from spam import *
    
    aaa()
    bbb()
    change()
    
    • 可以使用 __all__ 功能规定只能使用的模块
    ⛅比如在 "spam.py" 文件中加入
    __all__=["aaa","change"]
    
    ⛅那么在另一个文件中导入这个文件就只能使用这两个规定的名字
    

    四.模块的循环导入问题

    1.什么是循环导入问题

    • 模块循环/嵌套导入抛出异常的根本原因是由于在python中模块被导入一次之后,就不会重新导入,只会在第一次导入时执行模块内代码

    2.循环导入演示

    • 文件 : run.py, m1.py, m2.py
    ⛅"run.py"
    import m1
    
    m1.f1()
    
    ⛅"m1.py"
    print('正在导入m1')
    
    from m2 import y
    
    x='m1'
    
    ⛅"m2.py"
    print('正在导入m2')
    
    from m1 import x
    
    y='m2'
    
    ⛅测试一 : 执行"run.py"
    执行"run.py",导入"m1", 并运行其内部代码, 打印"m1"内容"正在导入m1"
    接着开始导入"m2"并运行其内部代码, 打印内容"正在导入m2"
    "m2"中又导入"m1"由于"m1"已经被导入过了,所以不会重新导入
    于是直接去'm1'中获取"x",然而"x"此时还没来的急定义在"m1"中,所以报错
    
    ⛅测试二 : 执行"m1.py"
    执行"m1.py",打印"正在导入m1",开始导入"m2"模块进而执行"m2.py"内部代码
    打印"正在导入m2",导入"m1"模块,此时"m1"是第一次被导入,打印"正在导入m1"
    紧接着执行"from m2 import y",由于"m2"已经被导入过了,所以直接向"m2"获取"y"
    然而"y"此时并没有来得及定义在"m2"中, 所以报错
    

    3.解决方法

    • 我们的项目中应该尽量的避免出现循环 / 嵌套调用
    • 如果有多个模块都需要使用共同的功能, 应该将其放入到一个共享文件里去
    • 如果程序已经出现了循环 / 嵌套调用, 解决方法如下
    ⛅方法一 : 将导入语句放入最后
    "m1.py"
    print('正在导入m1')
    x='m1'
    
    from m2 import y
    
    "m2.py"
    print('正在导入m2')
    y='m2'
    
    from m1 import x
    
    ⛅方法二 : 将导入语句放入函数中
    "m1.py"
    print('正在导入m1')
    
    def f1():
        from m2 import y
        print(y)
    
    x='m1'
    
    "m2.py"
    print('正在导入m2')
    
    def f2():
        from m1 import x
        print(x)
    
    y='m2'
    

    五.Py文件的两种用途

    1.两种用途

    • 脚本 : 一个文件就是整个程序, 用来被执行

    • 模块 : 文件中存放着一堆功能, 用来被导入使用

    2.执行py文件与被导入py文件名称空间的区别

    • 执行py文件 : 程序执行完毕后名称空间回收
    • 被导入的py文件 : 当执行文件运行完毕后,导入模块的文件才会跟着结束

    3.Python内置变量 __name__

    • 该变量在py文件被当做脚本执行时赋值为__main__
    • 该变量在py文件被当做模块导入时赋值为模块名
    ⛅可以在导入模块写内容测试一下:
    if __name__ == '__main__':
    	print('我被执行了')    # 导入模块自己测试执行会打印
    else:
    	print('我被导入了')    # 执行文件导入该模块会被打印
    

    六.模块的搜索路径

    1.模块的查找顺序

    • 内存中已经加载的模块
    • 内置模块
    • sys.path 中包含的模块

    ps : 模块的导入查找的起始点就是当前执行文件所在的目录

    2.内存优先级测试

    import time
    import m1       # 导入 m1
    
    m1.f1()         # 已经读到内存里面
    time.sleep(15)  # 在15秒之内删除 m1.py
    import m1       # 这一行还可以调用
    m1.f1()         # 没有影响
    

    3.内置模块优先级测试

    • 新建一个自定义 time.py 文件
    • run.py 里调用自定义
    ⛅"time.py"文件内容
    print("这是自定义模块")
    
    ⛅"run..py"文件内容
    import time  # 首次导入
    
    print(time.time())  # 1607586947.3936024
    
    执行该文件, 发现并没有打印 "这是自定义模块", 而是触发了内置模块"time"的功能
    

    4.sys.path 环境变量介绍

    • 查看 sys 环境变量
    import sys
    
    print(sys.path)
    '''
    ['F:\\Pycharm File\\PycharmProjects\\python正课\\day17',\
    'F:\\Pycharm File',\
    'J:\\PyCharm 2020.2.3\\plugins\\python\\helpers\\pycharm_display',\
    'K:\\python37\\python37.zip',\
    'K:\\python37\\DLLs',\
    'K:\\python37\\lib',\
    'K:\\python37',\
    'K:\\python37\\lib\\site-packages',\
    'J:\\PyCharm 2020.2.3\\plugins\\python\\helpers\\pycharm_matplotlib_backend']
    '''
    可以发现是一个列表 (代表着可以使用 "append" 功能向里面添加路径)
    第一个路径是当前执行文件所在的目录
    第二个是整个项目的路径, "PyCharm" 的优化 (在别的编辑器上没有,可以忽略)
    第四个是 "zip" 格式压缩包, 其实它是python解释器,里面放的是内置以及标准库模块
    其他的一些都是第三方库或者自定义下载的模块
    

    ps : 添加文件路径到 sys 环境变量

    import sys
    sys.path.append("[文件路径]")
    
    例:
    import sys
    sys.path.append("F:\Pycharm File\PycharmProjects\python正课\day10")
    print(sys.path[-1])  # F:\Pycharm File\PycharmProjects\python正课\day10
    

    5.总结注意点

    • 如果自定义模块名与内置和第三方名相同, 则会先调用内置的, 所以名字尽量不要与内置和第三方相同
    • 强调 : sys.path 的第一个路径是当前执行文件所在的文件夹

    梦里有我闻过的花香 也有我与你初遇的地方

  • 相关阅读:
    get和post
    java学习day34-Cookie技术
    java学习day33-Maven-相关
    在Linux设置完共享文件夹后无法显示Windows里的文件
    Tomcat-把tomcat的端口号从8080修改为80
    是否忘记向源中添加“#include“StdAfx.h””
    php-fpm配置文件详解
    Web安全常见漏洞修复建议
    blog个性化设置
    使用 notepad++ 编辑器在行首、行尾添加字符
  • 原文地址:https://www.cnblogs.com/songhaixing/p/14109628.html
Copyright © 2011-2022 走看看