zoukankan      html  css  js  c++  java
  • 模块与包

    模块

    模块基础

    模块就是一系列功能的集合体,也就是一堆函数的集合体。因此一个py文件就可以看成一个模块

    我们的程序从面条型---》函数版本---》文件版(模块)---》文件夹版(包)

    模块的分类

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

    import 与from...import...

    我们定义好的模块是拿过来使用的,所以我们可以通过import与from...import...来导入模块

    import模块

    import time
    
    time.sleep(1)
    

    import导入函数会经过如下三个步骤(以上面函数为例):

    1. 先到开time模块文件
    2. python解释器运行time模块,然后把time模块名字放入time模块名称空间
    3. 主程序中就会有一个变量time指向time模块名称空间

    from...import...模块

    from time import sleep
    
    sleep(1)
    

    from...import...导入函数会经过如下三个步骤(以上面函数为例):

    1. 先到开time模块文件
    2. python解释器运行time模块,然后把time模块名字放入time模块名称空间
    3. 主程序中就会有一个变量sleep指向time模块名称空间里的sleep函数

    循环导入问题

    当我们写程序的时候,调用的模块比较频繁,不可避免模块之间的相互调用,这样就有可能出现循环导入问题

    # m1.y
    from m2 import y
    x = 10
    
    
    # m2.py
    from m1 import x
    y = 20
    

    如上两个模块之间的相互调用就会出现循环导入问题

    1. m1文件导入m2文件的y
    2. m2文件导入m1文件的x
    3. 因为代码是自上而下运行的,所以在运行m1模块时,会去m2文件找y,但m2模块首先就是去m1模块找x,这样就又回到了m1模块,这样就陷入了循环导入,会报错

    解决方案一

    # m1.y
    x = 10
    from m2 import y
    
    
    # m2.py
    y = 20
    from m1 import x
    
    

    将需要调用的放到导入模块之前,这样m1,m2就能找到需要的x,y

    但这样做,需要对所有变量都这么做,才能解决问题,没有完美的解决

    解决方案二

    # m1.y
    def f1():
        from m2 import y
        
    x = 10
    f1()
    
    
    # m2.py
    def f2():
        from m1 import x
        
    y = 10
    f2()
    

    将模块调用放入到函数中,这样全局变量就会先生成,函数会在文件运行的时候再生成

    执行顺序:内置名称空间--》全局名称空间---》局部名称空间

    模块的搜索路径

    1. 去内存中查找
    # 验证办法
    
    import m1   # 此时m1模块已在内存空间
    
    import time
    
    # 删除m1模块
    time.sleep(10)
       
    import m1    # 此时m1文件已不存在,但不报错,所以是在内存中找到了m1模块
    
    1. 去内置模块中找
    # 验证办法
    
    # time.py
    print('from time')
    
    
    import time   # 无任何打印,证明先去内置模块中找
    
    1. 环境变量中找
    import sys
    
    print(sys.path)
    
    # b/a/m1.py
    
    # b/test.py
    import m1  # 报错
    
    sys.path.append('b/a')
    import m1   # 不报错
    

    Python文件的两种用途

    1. 当作模块文件进行导入,可以有多个
    2. 当作运行文件,进行文件执行,只能有一个
    # m1.py
    def f1():
        print('from f1')
        
    f1()
    
    # test.py
    import m1
    
    m1.f1()  # 运行两次
    
    • _name_
    # m1.py
    def f1():
        print('from f1')
        
    if __name__ == '__main__':  # __name__在m1.py被当做模块导入时是模块名,作为执行文件时是'__main__'
        f1()
        
    
    # test.py
    import m1
    
    m1.f1()  # 运行一次
    

    批量生成文件

    import compileall
    compileall.compile_dir('$dir')
    
    其中,$dir 为Python源代码所在的目录。
    

    什么是包

    包是模块的一种形式,包的本质就是一个含有__init__.py的文件的文件夹。

    为什么要有包

    主要是因为当我们模块太大是,不能更好的去管理,所以可以把这个模块分为多个模块,但我们又不能改变模块的调用方式,就出现了包的概念

    如何使用包

    导入模块发生的三件事:

    1. 创建一个包的名称空间
    2. 执行py文件,将执行过程中产生的名字存放于名称空间中。
    3. 在当前执行文件中拿到一个名字aaa,aaa是指向包的名称空间的

    导入包发生的三件事:

    1. 创建一个包的名称空间
    2. 由于包是一个文件夹,无法执行包,因此执行包下的__init__.py文件,将执行过程中产生的名字存放于包名称空间中(即包名称空间中存放的名字都是来自于__init__.py)
    3. 在当前执行文件中拿到一个名字aaa,aaa是指向包的名称空间的

    导入包就是在导入包下的__init__.py,并且可以使用以下两种方式导入:

    1. import ...
    2. from ... import...
    # aaa.py
    
    def f1():
        pass
    
    def f2():
        pass
    
    def f3():
        pass
    
    def f4():
        pass
    
    def f5():
        pass
    
    def f6():
        pass
    
    def f7():
        pass
    
    def f8():
        pass
    
    

    以上aaa模块里面函数看起来就很多,我们把aaa模块分为三个模块

    # m1.py
    
    def f1():
        pass
    
    def f2():
        pass
    
    def f3():
        pass
    
    # m2.py
    
    def f4():
        pass
    
    def f5():
        pass
    
    def f6():
        pass
    
    
    # m3.py
    
    def f7():
        pass
    
    def f8():
        pass
    
    # aaa/__init__.py
    from m1 import *
    from m2 import *
    from m3 import *
    
    # run.py
    
    from aaa import *
    f1()
    f2()
    ...
    

    其实我们在导入aaa时其实是导入的aaa里面的__init__.py文件,这样我们就做到了在不改变调用方式的情况下把aaa.py模块变成了一个包

    注意事项

    1. 包内所有的文件都是被导入使用的,而不是被直接运行的

    2. 包内部模块之间的导入可以使用绝对导入(以包的根目录为基准)与相对导入(以当前被导入的模块所在的目录为基准),推荐使用相对导入

    3. 当文件是执行文件时,无法在该文件内用相对导入的语法,只有在文件时被当作模块导入时,该文件内才能使用相对导入的语法

    4. 凡是在导入时带点的,点的左边都必须是一个包,import aaa.bbb.m3.f3错误

  • 相关阅读:
    AJAX
    JQUERY基础
    PHP 数据库抽象层pdo
    会话控制:session与cookie
    php 如何造一个简短原始的数据库类用来增加工作效率
    php 数据访问(以mysql数据库为例)
    面向对象设计原则
    php 设计模式 例子
    PHP中静态与抽象的概念
    键盘的按钮键名
  • 原文地址:https://www.cnblogs.com/Hades123/p/11019667.html
Copyright © 2011-2022 走看看