zoukankan      html  css  js  c++  java
  • Python学习第四天----模块儿导入

    1.命名空间

      模块儿的名字加上文件的名字,就是命名空间。
      python如何区分一个普通的文件夹和一个包的?
        在一个文件夹下有一个特定的文件__init__.py,此时这个文件夹就是一个包。(前后各两个下划线)。其中,这个文件本身也是一个模块儿。这个模块儿的名字就是他的直属文件夹的名字。
     

    2.模块儿的引入:

      第一种:

     
     
      我们不能直接导入模块儿下的变量的。
      修改引入模块儿的名字:
    import t.c7 as m 
    print(m.a)

      第二种:

    from t.c7 import a 
    print(a) //或者 # from t import c7 #print(c7.a)
      引入所有的变量:
    from t.c7 import * 
    print(a) 
    print(c) 
    print(d)
      其中t.c7中的变量定义为:
    a = 2
    c = 3
    d = 4
      在t.c7中可以指定通过*号导出变量或者函数,如下值导出a,c变量:
      t.c7.py:
    __all__ = ['a', 'c']   
      
    a = 2     
    c = 3     
    d = 4
      此时执行c8.py文件:
    from t.c7 import *
    
    print(a)
    print(c)
    print(d) 
    //2
    //3
    //Traceback (most recent call last):
    //  File ".c8.py", line 9, in <module>
    //    print(d)
    //NameError: name 'd' is not defined
      其中__all__称为模块儿的内置变量。

    第三种:

    from c9 import a,b,c
    
    '''
        from c9 import a
        from c9 import b
        from c9 import c
    '''
    python建议: 一行字符的个数最好不要超过80个
    此时涉及到换行而不改变代码本意:
    from c9 import a,b,
    c  
    上边示例并不建议,显得很突兀,所以建议使用括号来进行:
    from c9 import (a,b,
    c)
     

    3.__init__.py文件的作用:

     

    单个导入:

     
      导入包的时候, 该文件会自动执行。
      c11文件中:
    import t
      此时执行c11.py:
    #This is __init__.py file t中的__init__.py文件自动执行。
      当然,只引用t中的c7文件,__init__.py依旧可以执行。
      在 __init__.py文件中写入:
    __all__ = ['c7']
      在t文件夹下加入c8.py文件,c8.py文件中写入:
    e = 2 
    f = 3  
    g = 4
      c11文件中写入,并运行c11
    from t import * 
    print(c7.a) 
    #2 
    print(c8.e) 
    #error: NameError: name 'c8' is not defined
     

      批量导入:

        关于项目目录:
        在t文件夹下的 __init__.py中批量导入模块儿:
    import sys
    import datetime 
    import io
      在c13文件下引用:
    import t
    print(t.sys.path)
    #['F:\pythonlearn\my-pythonFirst\six', 'E:\py3\python38.zip', 'E:\py3\DLLs', 'E:\py3\lib', 'E:\py3', 'C:\Users\Administrator\AppData\Roaming\Python\Python38\site-packages', 'E:\py3\lib\site-packages']

    包与模块儿:

        1.包与模块儿是不会被重复导入的:
        2.避免循环导入
     
        什么是循环导入呢?
        例如,新建P文件夹,在p文件夹下有p1和p2两个文件:
        p1中:
    from p2 import p2 
    p1 = 2 
    print(p2)
      p2中:
    from p1 import p1 
    p2 = 2
      此时执行p1就会报错。
    Traceback (most recent call last):
      File ".p1.py", line 1, in <module>
        from p2 import p2
      File "F:pythonlearnmy-pythonFirstsixpp2.py", line 1, in <module>
        from p1 import p1
      File "F:pythonlearnmy-pythonFirstsixpp1.py", line 1, in <module>
        from p2 import p2
    ImportError: cannot import name 'p2' from partially initialized module 'p2' (most likely due to a circular import) (F:pythonlearnmy-pythonFirstsixpp2.py)
     
      import 导入的同时,就会执行被导入模块儿的代码。
     

    模块儿的内置变量:

    a = 2
    c = 3
    
    infos = dir();
    print(infos)
    # ['__annotations__', '__builtins__', '__cached__', '__doc__', '__file__', '__loader__', '__name__', '__package__', '__spec__', 'a', 'c']
      打印内置变量里的具体信息:先看结构
      1.在c9.py中:
    '''
    
        This is a c9 doc
    
    '''
    
    
    print("name:"+__name__)
    print("package:"+__package__)
    print("doc:"+__doc__)
    print("file:"+__file__)
      2.在c15中引入:
    import t.t1.c9
        此时的打印结果:
    name:t.t1.c9
    package:t.t1
    doc:
    
        This is a c9 doc
      如果c9中没有上边的注释,则会报错:
    TypeError: can only concatenate str (not "NoneType") to str
     

    入口文件和普通模块内置变量的区别:

     
      修改c15.py
    import t.t1.c9
    
    print("name:"+__name__)
    print("package:"+__package__)
    print("doc:"+__doc__)
    print("file:"+__file__)
      打印结果:
    name:t.t1.c9
    package:t.t1
    doc:
    
        This is a c9 doc
    
    
    file:F:pythonlearnmy-pythonFirstsix		1c9.py
    name:__main__
    Traceback (most recent call last):
      File ".c15.py", line 9, in <module>
        print("package:"+__package__)
    TypeError: can only concatenate str (not "NoneType") to str
      继续修改:
    '''
    描述
    '''
    import t.t1.c9
    
    print('~~~~~~~~~~~~~~~~~~~~c15~~~~~~~~~~~~~~~~~~~~~~~~~')
    print("name:" + __name__)
    print("package:" + (__package__ or '当前模块不属于任何包'))
    print("doc:" + __doc__)
    print("file:" + __file__)
      打印结果:
    name:t.t1.c9
    package:t.t1
    doc:
    
        This is a c9 doc
    
    
    file:F:pythonlearnmy-pythonFirstsix		1c9.py
    ~~~~~~~~~~~~~~~~~~~~c15~~~~~~~~~~~~~~~~~~~~~~~~~
    name:__main__
    package:当前模块不属于任何包
    doc:
    描述
    
    file:.c15.py
      总结: 因为运行的是c15.py文件,因此它是一个入口文件,所以不属于任何包。而c9从t下的t1引入,所以c9属于t.t1包。
      此外,file结果根运行时环境有关:
     
      对于dir()函数的补充:
     
      函数不带参数时,返回当前范围内的变量、方法和定义的类型列表;带参数时,返回参数的属性、方法列表。如果参数包含方法__dir__(),该方法将被调用。如果参数不包含__dir__(),该方法将最大限度地收集参数信息。
     
    对于一句代码的解读:
    if __name__ == "__main__":    
         pass
      可以用Make a script both importable and executable來概括:
      让你的脚本既可以提供一个脚本,供其他程序去调用,也可以自己作为一个可执行文件。
     
      当一个模块儿处于两种不同的情景的时候,在这两种情境中代码的逻辑是不同的,这个时候就需要用到这段程序。
      例如,在c17.py中写入:
    if __name__ == "__main__":
        print('This is app')
    
    print('This is a module')
      此时如果是直接执行该文件,可得到:
      
      This is app
      This is a module
      如果是被调用:
    This is a module
      这是因为,作为入口文件时,它的内置变量__name__的值就是__main__
      我们也可以通过命令来作为模块儿调用文件:
    python -m six.c17
      此时,c17是six文件夹下的py文件,命令行是在six的同级目录下进行(要让他称为一个模块,他就必须是一个包下的文件,否则会报错):
    PS F:pythonlearnmy-pythonFirst> python -m six.c17 
    This is app
    This is a module
      对于以上代码注意:
        ① 如果six下没有__init__.py,则找不到c17这个文件
        ② 如果是在six目录下执行:
    PS F:pythonlearnmy-pythonFirstsix> python -m c17
    This is app
    This is a module
    
    //-m 后边如果是文件,则会报错
    PS F:pythonlearnmy-pythonFirstsix> python -m .c17.py
    E:py3python.exe: Relative module names not supported
      对于根目录下的c15执行命令:( python -m six.c15)
    '''
    描述
    '''
    import t.t1.c9
    
    print('~~~~~~~~~~~~~~~~~~~~c15~~~~~~~~~~~~~~~~~~~~~~~~~')
    print("name:" + __name__)
    print("package:" + (__package__ or '当前模块不属于任何包'))
    print("doc:" + __doc__)
    print("file:" + __file__)
      会报错,报错内容是找不到文件t,此时需要在t文件前加six.
    '''
    描述
    '''
    import six.t.t1.c9
    
    print('~~~~~~~~~~~~~~~~~~~~c15~~~~~~~~~~~~~~~~~~~~~~~~~')
    print("name:" + __name__)
    print("package:" + (__package__ or '当前模块不属于任何包'))
    print("doc:" + __doc__)
    print("file:" + __file__)
      打印出来的name和package是:
    name:six.t.t1.c9 
    package:six.t.t1
      此处涉及到了相对导入和绝对导入的问题。此时,-m 后边跟的是命名空间。
     

      相对导入与绝对导入:

      绝对导入:

      1.入口文件的位置决定着__package__。
      m2文件:
    print(__package__);
      执行main.py
    Module2.Module4
      将main.py移动到Module2中,并修改main中的引入为Module4.m2,执行main.py
    Module4
      说明入口文件决定着这个命名空间。
      绝对路径: 从顶级包开始向下找。

      相对路径:

        一个点表示当前目录,两个点表示上一层目录,三个点表示上上层目录,通过n个点表示上n-1层目录
        但是import不能使用相对路径,但是可以使用from。main引用不能使用相对路径,原因是作为入口文件,被python执行后,它的name指的是__main__。而__main__是不存在的,所以在入口文件是不能使用相对路径的。但是可以通过使用-m来使得入口文件作为模块。
     
      包内文件不能使用相对路径引用顶层文件。如下图:
      原因是m5的顶层包是Module2,mian.py是一个入口文件,它的同级别目录下是没有__main__这个包的。
     

  • 相关阅读:
    DataGridView 复选框 操作大全
    ClickOnce 创建桌面快捷方式
    测量程序经过的时间
    C# Js 时间格式化问题
    MVC 漫长之路(一)
    SQL 查一年内的数据
    DataRow对象的RowState和DataRowVersion属性特点
    iOS打开百度地图、高德地图导航
    NSURLCache 和 NSCache 的区别
    MagicalRecord的使用(第三方库实现的数据库)
  • 原文地址:https://www.cnblogs.com/dsweb/p/14062768.html
Copyright © 2011-2022 走看看