zoukankan      html  css  js  c++  java
  • Python 模块化 from .. import 语句介绍 (二)


    from语句


    例一、

    from pathlib import Path,PosixPath
    
    print(dir())
    print(Path)
    print(PosixPath)
    
    运行结果:
    ['Path', 'PosixPath',...]
    <class 'pathlib.Path'>
    <class 'pathlib.PosixPath'>
    

      Path和PosixPath是pathlib模块中定义的类,使用 "from .. import .."语句可以直接映射pathlib模块中的资源在当前的命名空间。接下来就可以使用资源名直接调用,不需要再以"pathlib.Path" 这样的完整资源层次关系调用。

    例二、

    from pathlib import Path,PosixPath
    import pathlib.Path
    
    print(dir())
    print(Path)
    print(PosixPath)
    print(pathlib.Path)
    
    运行结果:
    Traceback (most recent call last):
    File "C:/python/1207.py", line 2, in <module>
    import pathlib.Path
    ImportError: No module named 'pathlib.Path'; 'pathlib' is not a package
    

      

    包的简单概念:
    包必须是目录,且此目录下有一个__init__.py,比如下面的层级关系:

    |--包

       |--__init__.py
       |--子模块.py
       |--子模块
          |--子模块.py


    包下面可以有多个嵌套的子模块,后面会单独一篇文章介绍包。


    模块必须是一个文件夹或者单独的以py结尾的文件,比如下面的层级关系:
    |--os
       |--path.py

    上面的树状文件路径中os是一个顶级模块,path是os模块下的一个子模块。


    再看下pathlib的层级关系:
    |--pathlib.py
       |--class Path(PurePath)
    上面的pathlib就是一个单独的顶级模块,Path只是这个模块中的一个类,并不是一个模块,所以import pathlib.Path 直接导入时会抛出 No module named 'pathlib.Path' 异常。


    如果需要直接导入模块里面的资源就必须使用 from 模块 import 资源名 的格式,下一个例子就会介绍这种格式。

    例三、

    from pathlib import * #导入模块下的所有"公共"资源
    
    print(dir())
    print(Path.cwd())
    运行结果:
    ['Path', 'PosixPath', 'PurePath', 'PurePosixPath', 'PureWindowsPath', 'WindowsPath', ...]
    

      

    通过前一个例子的异常,我们知道import 无法直接导入顶级模块或子模块中的资源(类,方法,属性),使用 from .. import * 语句(第一种方法)就会将指定模块下的所有资源导入,或者指定资源名的格式导入部分资源: from .. import 资源(第二种方法) ,这两种方法都会将资源同名映射到当前命名空间。
    第二种方法相比第一种方法的好处是,只导入需要的资源,其它用不到的资源通通不导入,可以节省内存,这是一种好的编程习惯,在程序效率上任何微小的提升积累起来都是大的提升。

    本例子中特别强调了 from .. import * 导入的是模块下的所有”公共“资源,公共资源也就是不以单下划线(_xx)或者双下划线(__yy__)开头的资源。

    例四、

    from os import path as osp #别名
    print(dir())
    
    运行结果:
    ['__builtins__', '__cached__', '__doc__', '__file__', '__loader__', '__name__', '__package__', '__spec__', 'osp']
    

      在导入子模块或者资源时也可以使用as 语句重命名子,当前命名空间最终保存的就是重命名后的映射。


    例五、

    from os.path import exists
    
    print(dir())
    if exists('c:/windows'):
    print('found')
    else:
    print('not found')
    
    运行结果:
    ['__builtins__', '__cached__', '__doc__', '__file__', '__loader__', '__name__', '__package__', '__spec__', 'exists']
    found
    

      当前例子中使用了 from 包.模块 import 子模块 的格式,说明from语句后的模块可以是完整层级关系下的模块(依然有一个找模块、加载模块、初始化模块的过程),也可以是单独的模块,最终当前加入命名空间的依然是子模块名的映射。

    例六、

    from os.path import exists
    
    print(dir())
    print(exists)
    
    import os
    print(dir())
    print(os.path.exists)
    print(os.path.__dict__['exists'])
    
    运行结果:
    ['__builtins__', '__cached__', '__doc__', '__file__', '__loader__', '__name__', '__package__', '__spec__', 'exists']
    <function exists at 0x000001F7AEDAC268>
    ['__builtins__', '__cached__', '__doc__', '__file__', '__loader__', '__name__', '__package__', '__spec__', 'exists', 'os']
    <function exists at 0x000001F7AEDAC268>
    <function exists at 0x000001F7AEDAC268>
    

      

    当前例子中先后使用不同的导入方式,导入path模块的exists函数,最终比较内存地址时,按道理说前后调用的方式是不一样的,却发现内存地址是一致的。
    模块加载机制中可能有一种在当前环境中防止重复导入模块的机制,下一篇文章再做介绍。


    总结:

    1. from 语句需要指定模块,模块可以是单独的顶级模块,也可以是层级关系下的子模块,加载并初始化该模块

    2. import 语句后指定的是该模块的资源(类,方法,函数),或者导入该模块下的子模块。

         先查找导入的模块是具有该名称的属性 -->如果没有,就尝试导入为该名称的子模块 --> 如果还没有找到,就抛出ImportError异常。下一篇文章也会举例介绍该模块搜索顺序。

         如果该名称后有as语句,则关联as语句后的名称到当前名词空间

  • 相关阅读:
    “XXXXX” is damaged and can’t be opened. You should move it to the Trash 解决方案
    深入浅出 eBPF 安全项目 Tracee
    Unity3d开发的知名大型游戏案例
    Unity 3D 拥有强大的编辑界面
    Unity 3D物理引擎详解
    Unity 3D图形用户界面及常用控件
    Unity 3D的视图与相应的基础操作方法
    Unity Technologies 公司开发的三维游戏制作引擎——Unity 3D
    重学计算机
    windows cmd用户操作,添加,设备管理员组,允许修改密码
  • 原文地址:https://www.cnblogs.com/i-honey/p/8031218.html
Copyright © 2011-2022 走看看