模块

作者: szn好色仙人 | 来源:发表于2018-04-07 11:42 被阅读0次

    模块:宏伟蓝图

    • 每一个文件都是一个模块,并且模块导入其他模块之后就可以使用导入模块定义的变量名。
      import使客户端以一个整体获取一个模块
      from允许客户端从一个模块文件中获取特定的变量名
      imp.reload在不中止python程序的情况下,提供了一种载入模块文件代码的方法

    • 导入是运行时的运算,程序第一次导入指定文件时,会执行三个步骤:找到模块文件、编译成位码、执行模块代码来创建其所定义的对象。

    模块代码编写基础

    • 就像def一样,import和from都是可执行语句,而不是编译期间的声明,而且他们可以嵌套在if测试中,出现在函数def之中等,直到程序执行时,才会进行解析。被导入的模块和变量名直到他们对应的import或from语句执行后,才可以使用。就像def一样,import和from都是隐性的赋值语句

    • 以from复制的变量名会变成对共享对象的引用,对已取出的变量名重新赋值,对于其复制之处的模块并没有影响,但是修改一个可变对象,则会影响导入的模块内的对象。为了实际修改另一个文件中的全局变量名,必须使用import

    #Del.py
    print('Del.py')
    x = 1
    y = [0, 1]
    
    
    #Test.py
    from Del import x, y
    import Del
    
    print('Main:Before Change', x, y)
    print('Del:Before Change', Del.x, Del.y)
    x = 'szn'
    y[0] = 'szn'
    print('Main:After Change', x, y)
    print('Del:After Change', Del.x, Del.y)
    
    Del.x = "szn"
    print('Deal:Use Import Change:', x)
    
    #Test.py输出结果:
    Del.py
    Main:Before Change 1 [0, 1]
    Del:Before Change 1 [0, 1]
    Main:After Change szn ['szn', 1]
    Del:After Change 1 ['szn', 1]
    Deal:Use Import Change: szn
    
    >>> x, y = 1, [0, 1]
    >>> def Fun():
        a = x
        b = y
        a = 'szn'
        b[0] = 'szn'
    
        
    >>> Fun()
    >>> x, y
    (1, ['szn', 1])
    
    • from只是把变量名从一个模块复制到另一个模块,并不会对模块名本身进行赋值
    from moudle import name1, name2 
    
    import moudle
    name1 = moudle.name1
    name2 = moudle.name2
    del moudle
    
    #以上两段代码从概念上说,是一致的
    
    from Moudle import * #导出Moudle的所有属性
    
    • 在模块文件顶层,每一个赋值了的变量名都会成为该模块的属性

    • reload与import和from不同,他是一个函数而非语句。传给reload的是已经存在的模块对象,而非变量名
      reload会在模块当前命名空间内执行模块文件的新代码
      文件中顶层赋值语句回事的变量名换成新值
      reload会影响所有使用了import读取了模块的客户端
      reload只会对以后使用from的客户端造成影响,之前使用from读取的属性的客户端不受影响

    #Del.py  修改前
    print('Del.py')
    x = 1
    y = [0, 1]
    
    #Del.py  在执行time.sleep(10)修改后
    print('Del.py')
    x = 123
    y = [0, 123]
    
    
    #Test.py
    from imp import reload
    import time
    from Del import x, y
    import Del
    
    print('Use From Before Reload:',x, y)
    print('Use Import Before Reload:',Del.x, Del.y)
    
    time.sleep(10)
    reload(Del)
    print('Use From After Reload:',x, y)
    print('Use Import After Reload:',Del.x, Del.y)
    
    #输出
    Del.py
    Use From Before Reload: 1 [0, 1]
    Use Import Before Reload: 1 [0, 1]
    Del.py
    Use From After Reload: 1 [0, 1]
    Use Import After Reload: 123 [0, 123]
    

    模块包

    • 导入可以指定目录路径,python代码的目录称为包,因此,这类导入就称为包导入。包导入路径的最左边的部分仍是sys.path模块搜索路径中的一个目录
    • 包导入语句的路径中的每个目录内都必须有__init__.py这个文件。首次导入某个目录时,会自动执行该目录下的__init__.py文件中的所有代码。例如import dir1.dir2.mod,表达式dir1.dir2会返回一个模块对象,而此对象的命名空间包含了dir2的__init__.py所赋值的所有变量名。可以在__init.py__使用__all__列表来定义目录以from*语句导入时,需要导出什么
    #文件层级
    '''
    Test.py
    dir1
      __init__.py
      dir2
        __init__.py
        Test.py
    '''
    #Test.py
    import dir1.dir2.Test
    print(dir1.x)
    
    #dir1\__init__.py
    print('dir1.__init__')
    x = 'dir1'
    
    #dir1\dir2\__init__.py
    print('dir2.__init__')
    y = 'dir2'
    
    #dir1\dir2\Test.py
    print('Test.py')
    z = 'Test'
    
    #输出
    dir1.__init__
    dir2.__init__
    Test.py
    dir1
    
    • 在包自身的内部,包文件的导入可以使用和外部导入相同的路径语法,但是也可以使用特殊的包内搜索规则简化导入语句。
    • python3.0模块导入搜索路径语义默认的跳过包自己的目录,导入只是检索搜索路径的其他组件,这叫做绝对导入。比如在包文件中:import Test不会搜索包路径下的Test.py,而会搜索sys.path中包含的路径下的Test文件
    • python扩展了from的语法,允许显示的要求导入只搜索包的目录,这叫做相对导入,如下:
    from . import Test      #Test.py位于当前文件的相同包路径下
    from . Test import v    #导出处于当前文件的相同包路径下的Test.py中的v
    
    from .. import Test      #Test.py位于当前文件上层目录下
    from ... import Test      #Test.py位于当前文件上上层目录下
    #以此类推
    
    注意点:
    相对导入适用于只在包内导入
    相对导入只适用于from语句
    
    • 利用as来使用别名
      import dir1.dir2.dir3.dir4.Szn as Szn
      import MoudlName as MName
      from MoudleName import Name as N

    模块高级话题

    • from XXX import*细节
    • 把下划线放在变量名前,可以防止客户端使用from XXX import*语句导出模块名时,把其中的那些变量名复制出去。下划线不是私有声明,还是可以通过其他导入形式看见并修改这类变量名。
    • 在模块顶层把变量名的字符串列表赋值给变量__all__,来指定from XXX import*时导出的变量
    • python会首先寻找模块内的__all__,若未定义则from XXX import*会复制出开头没有下划线的所有变量名
    • 每个模块都有个名为__name__的内置属性,python会自动设置该属性:如果文件是以顶层程序文件执行,则此属性被设置为'__main__'。如果文件被导入,则此属性被设置为客户端所了解的模块名。结果就是模块可以检测自己的__name__,来确定自己是在执行还是被导入

    • 通过修改sys.path列表,来修改当前程序的模块搜索路径,此修改在程序结束后不会保存下来

    • getattr可以通过字符串名来取出属性

    #Szn.py
    s = 'szn'
    
    #Test.py
    import Szn
    print(getattr(Szn, 's'))
    
    #输出
    szn
    
    • eval(str)函数将字符串str当成有效Python表达式来求值,并返回计算结果。
      exec(str)函数将字符串str当成有效的Python表达式来执行,不返回计算结果
    >>> exec('1 + 2')
    >>> eval('1 + 2')
    3
    
    • __import__可以通过字符串导入模块
    #Szn.py
    print('Szn')
    s = 's'
    
    #Test.py
    s = __import__('Szn')
    print(s.s)
    
    #输出
    Szn
    s
    

    相关文章

      网友评论

          本文标题:模块

          本文链接:https://www.haomeiwen.com/subject/lqxyhftx.html