zoukankan      html  css  js  c++  java
  • 模块基础

    Python文件的两种运行方式

    1、脚本方式:

    • 直接解释器执行。

    2、模块方式:

    • 通过导入语句被其他文件导入,为导入它的文件提供资源(变量,函数定义,类定义等)。

    模块的定义

    • 本质就是文件,一系列功能的集合体。
    • 模块中出现的变量,for循环,if结构,函数定义。。。等称为模块的成员。

    对一些通用的功能,将它们提出来放进一个模块中,然后在各个地方导入使用,这样能增加开发效率,减少代码冗余。


    模块的四种通用的类别

    1、一个Python文件就是一个模块,文件名test.py,模块名则为test。

    2、盛放有多个Python文件的目录也是一个功能的集合体,也是一种模块,称之为包。

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

    4、使用C编写并链接到Python解释器的内置模块。


    模块的三种来源

    1、自带的模块。

    • 内置模块,集成在解释器内部。

      import time
      print(time)
      <module 'time' (built-in)>
      
    • 标准库

      import os
      print(os)
      <module 'os' from 'D:\\Python38\\lib\\os.py'>
      

    2、第三方模块

    一些开发者写的非常好的模块,需要同过pip命令安装的模块,比如Django。
    

    3、自定义模块。

    我们自己写的一些模块。
    

    模块导入

    模块导入的两种语句:

    import 模块名
    from 模块名 import 成员
    

    第一种的优点是能指名道姓的使用该模块的成员,不会产生名称冲突;缺点是每次使用都要加模块名前缀。

    第二种的优点是使用简单,不用加模块名前缀;缺点是容易与当前命名空间的名称产生冲突。


    模块导入的多种方式

    导入一个模块的所有成员。

    import module
    

    一次性导入多个模块的所有成员,不推荐这种写法。

    import module1, module2,module3......
    

    从某个模块中导入指定的成员。

    from module import a
    

    从某个模块中导入多个成员。

    from module import a,b,c
    

    从模块中导入所有成员,和import的区别是这种方式不用加模块名前缀。

    from module import * 
    

    使用from module import * 控制成员被导入

    • 默认情况下,所有成员都会被导入。
    • __all__是一个列表,用于表示本模块可以被外界使用的成员,元素是成员名组成的字符串。
    # 在模块内使用'__all__'控制被导入的成员。
    
    __all__ = [member1,member2,member3,...]
    

    在文件中使用from module import *导入时,只能使用列表内的成员,若要使用模块的所有成员,可以不使用from module import * ,从而绕过__all__的限制。


    怎么解决命名冲突的问题

    • 使用import module 导入。
    • 自己避免使用同名的名称。
    • 使用别名解决冲突。

    模块别名

    主要针对导入的模块和导入模块的成员,并非针对我们自己写的变量、函数、类等

    1、给成员起别名,避免命名冲突。

    form module import  member as mem_alias
    

    2、给模块起别别名,简化书写。

    import module as mod_alias
    

    as是alias的缩写。


    模块使用

    使用模块名加点.方式来调用模块下的成员。

    import time
    print(time.time()) # 表示使用time模块中的time()方法
    

    首次导入模块发生的事

    • 1、在内存中产生模块的名称空间,将模块运行的过程中产生的名字都丢到模块的名称空间中。
    • 2、执行模块名称空间中所有可执行代码。
    • 3、在当前文件中产生一个模块名称,该名称指向模块中产生的名称空间 。

    导入语句可以在程序中任意位置使用,为防止针对同一模块的多次导入重复占用内存空间,Python的优化手段是:

    第一次导入后就将模块名加载到内存了,后续的import语句进是针对已经加载到内存的模块对象增加了一次引用,不会重复执行模块内的语句


    导入后的名称空间

    • 被导入的模块有独立的名称空间,无论是查看还是修改操作的都是原模块,与调用位置无关
    • 模块的名称空间没有被引用后,则会被回收。
    • 模块也可以在函数中导入,导入后则只能在导入时的名称空间内使用,函数执行完毕后则名称空间被回收。
    def func():
        import time
        print(time.time())
    # 函数外则无法调用
    time.time()
    

    模块的导入规范

    约定俗称的顺序,便于读代码

    • 1、内置模块。
    • 2、第三方模块。
    • 3、自定义模块。

    循环导入问题

    指的是模块之间互相导入。例如,

    # 模块1中导入模块2。
    from m2 import n
    i = 1
    
    # 模块2中导入模块1。
    from m1 import i
    n = 2
    

    如果这时候,我们要在另一个执行文件中导入其中一个模块,就会报错。

    import m1
    
    ImportError: cannot import name 'i' from partially initialized module 'm1' (most likely due to a circular import)
    

    这是因为,在当前文件导入m1时,m1的代码执行导入m2,m2的代码执行又导入m1中的变量i,但此时变量i在m1中还没有定义(因为第一行from还没有执行完毕),所以会报错无法导入i

    首先,循环导入在构建代码逻辑时是一定要避免的,但若你的代码逻辑走到这一步,那么解决方式有4种:

    1、在导入模块前定义名称。

    n = 2
    from m1 import i
    

    2、将导入模块语句写在函数中,之后的函数调用在定义名称之后。

    def func():
        from m1 import i
        
    n = 2
    func()
    

    3、使用一个新文件,将俩模块公用部分放入新文件中。

    4、使用import导入也能避免该问题。

    控制模块被导入时是否运行

    一个模块往往包含多个功能,自定义模块被其他模块导入时,其中的可执行语句会立即执行,一般我们不希望模块内的函数直接执行,仅在需调用其中某些功能时才执行,解决方式是使用全局变量 _name_。

    • 当文件被当做脚本执行时,在文件内执行 print( _name_) 返回值是固定字符串 '__main__',表示当前是开发模式。
    print(__name__)
    
    __main__
    
    • 当文件被当做模块导入时,在模块内的 _name_ 等于模块原名(不包含.py后缀),表示当前是导入模式。
    # 在模块中判断__name__是否为'__main__'
    import time
    print(time.__name__)
    time
    

    使用__name__这个特性帮我们区分模块的两种运行方式:

    def func():
        pass
    
    if __name__ == '__main__':
        func()
        # 如果为True则表示是开发模式,则执行函数。
        # 如果为False则是导入模式,则不会执行
    
    此语句经常使用,Pycharm提供了一个快捷方式,直接输入 main 然后回车即可。
    

    模块的搜索路径优先级

    Python中导入模块是按照一定的规则以及顺序去寻找的。

    1、内存中

    • 如果之前成功导入过某个模块,则直接使用已经存在的模块。
    # sys.modules查看已经加载到内存中的模块
    
    import sys
    print(sys.modules)
    
    输出为一个字典,模块名为key,value是导入位置
    

    2、内置模块

    • Python解释器的安装路径中Lib目录下,所有以 .py结尾的文件,都是自带模块。
    • Lib目录中的site-packages目录,一些来源网络的第三方模块,就放在这个目录中。

    3、sys.path路径

    • 是一个路径的列表。通常导入自定义的模块时,将自定义模块的目录添加至此列表中。
    import sys
    print(sys.path)
    
    # ['D:\\Desktop\\Netfile\\Python\\Program\\Py_programs', 
    'D:\\Desktop\\Netfile\\Python\\Program\\Py_programs', 'D:\\PyCharm 
    2020.1.1\\plugins\\python\\helpers\\pycharm_display', 'D:\\Python38\\python38.zip', 
    'D:\\Python38\\DLLs', 'D:\\Python38\\lib', 'D:\\Python38', 
    'D:\\Python38\\lib\\site-packages', 'D:\\PyCharm 
    2020.1.1\\plugins\\python\\helpers\\pycharm_matplotlib_backend']
    

    第一个路径是当前执行文件的所在目录,第二个目录在pycharm中的话,它会做一个优化,将当前项目这个顶级目录也添加入sys.path列表中。


    添加模块所在目录的绝对路径

    对于我们自定义的模块或下载的第三方模块,如果模块的所在目录不在sys.path列表中,那么就不能直接导入,解决方式就是在列表中添加模块所在目录的路径。

    sys.path.append(r'/path/moudir')
    

    sys.path添加路径是临时添加,程序运行结束后恢复。

    sys.path环境变量是以执行文件为准的,被导入的模块或后续其他文件引用的sys.path都是参照执行文件的sys.path。

    import sys
    
    sys.path.append('abcdefghijklmnopqrstuvwxyz')
    print(sys.path)
    
    import modu1     # modu1中有一行print(sys.path)语句
    print('下面是模块的sys.path.............')
    

    结果为:

    ['D:\\Desktop\\Netfile\\Python\\Program\\Py_programs', 'D:\\Desktop\\Netfile\\Python\\Program\\Py_programs', 'D:\\PyCharm 2020.1.1\\plugins\\python\\helpers\\pycharm_display', 'D:\\Python38\\python38.zip', 'D:\\Python38\\DLLs', 'D:\\Python38\\lib', 'D:\\Python38', 'D:\\Python38\\lib\\site-packages', 'D:\\PyCharm 2020.1.1\\plugins\\python\\helpers\\pycharm_matplotlib_backend', 'abcdefghijklmnopqrstuvwxyz']
    
    下面是模块的sys.path.............
    
    ['D:\\Desktop\\Netfile\\Python\\Program\\Py_programs', 'D:\\Desktop\\Netfile\\Python\\Program\\Py_programs', 'D:\\PyCharm 2020.1.1\\plugins\\python\\helpers\\pycharm_display', 'D:\\Python38\\python38.zip', 'D:\\Python38\\DLLs', 'D:\\Python38\\lib', 'D:\\Python38', 'D:\\Python38\\lib\\site-packages', 'D:\\PyCharm 2020.1.1\\plugins\\python\\helpers\\pycharm_matplotlib_backend', 'abcdefghijklmnopqrstuvwxyz']
    

  • 相关阅读:
    自定义瀑布流
    传值 属性 block 单例 协议
    sqlite数据库中 保存和读取UIData对象
    SQL
    关于在Xcode控制台打印的注意点
    synthesize的作用
    iPhone屏幕尺寸/launch尺寸/icon尺寸
    关于TableView上有一段留白的解决方法
    mac显示隐藏文件
    多线程之GCD
  • 原文地址:https://www.cnblogs.com/ChiRou/p/13358730.html
Copyright © 2011-2022 走看看