zoukankan      html  css  js  c++  java
  • python——包模块

    0.引言

    一般的包导入模式是通过以下语句执行:

    import dir1.dir2.mod
    # . 表示路径的间隔,相当于Linux下的/
    # 而mod表示的是该路径下有一个文件叫mod.py ,而这里的.py被省略了

      但是在使用包导入就必须遵守一条约束:包导入语句的路径中的每个目录内都必须有__init__.py,也就是说dir1,dir2中都必须要有__init__.py这个文件。

    对于以上的这种import语句,必须遵守下列规则:

    • dir1和dir2中都必须包含有一个__init__.py文件
    • dir0是容器,不需要__init__.py文件,如果有的话,这个文件也会被忽略。
    • dir0(而非dir0dir1)必须列在模块搜索路径上(也就是此目录必须是主目录,或者列在PATHONPATH之中)

    而在Pycharm中的设置是通过给File->Settings->project structure中设置root以及对容器进行Mark为source(源文件),excluded(排除)来进行标记的。

    1.__init__.py

    __init__.py可以包含Python 程序代码,就像普通模块文件。这类文件从某种程度上讲就像Python的一种声明,尽管如此,也可以完全是空的。作为声明,这些文件可以防止有相同名称的目录不小心隐藏在模块搜索路径中,而之后才出现真正所需要的模块。

    __init__.py文件扮演了包初始化的钩子、替目录产生模块命名空间以及使用目录导入时实现from *(from ... import *)行为的角色。包可以使用其初始化文件(__init__.py)来创建所需要的数据文件,连接数据库等。

    from *语句的行为:作为一个高级功能,你可以在__init__.py文件内使用__all__列表来定义目录以from * 语句形式导入时,需要导入什么。

    在__init__.py文件中__all__列表是指当包(目录)名称使用from *的时候,应该导入的子模块的名称清单。如果没有设置__all__,from *语句不会自动加载嵌套于该目录内的子模块。取而代之的是,只加载该目录的__init__.py文件中赋值语句定义的变量名。包括该文件中程序代码明确带入的任何子模块。

    2.相对导入

    from 语句现在可以使用前面的点号(“.”)来指定,他们需要位于同一包中的模块(所谓的包相对导入),而不是位于模块导入搜索路径上某处的模块(叫绝对导入)。

    比如某文件夹下存在__init__.py, a.py, b.py,如果想在b.py中导入a模块。

    import b #不推荐,如果b这个名字是不存在的相同的模块,则最终还是会起到下面的相同效果
    from . import b # 推荐这是相对导入的正确写法,也是强制相对导入
    from .a import var1 # 从名为a的模块导入变量var

    注:“.”是指的当前程序运行的路径,即相对路径;如果不使用 "."而是以"lib"之类的开头,就已经不再是相对导入了,而是绝对导入,这个时候会根据你的sys.path中的容器(左到右)来查找lib这个含有__init__.py的模块。

    但是在python2.x中默认先相对再绝对的搜索顺序,而python3.x则是先绝对再相对的搜索顺序。为了保持python2和python3中的代码一致性(即编写在python2中也兼容的代码),应该加上如下语句:

    from __future__ import absolute_import

     相对导入的作用域:

    • 相对导入适用于只在包内导入。
    • 相对导入只是用于from语句。且一个from中的模块名前面有一个或者多个点号。

    模块查找规则总结:

    • 简单模块名(例如,A)通过搜索sys.path路径列表上的每个目录来查找,从左到右进行。这个列表由系统默认设置和用户配置设置组成。
    • 包是带有特殊__init__.py文件的pychon模块的直接目录。这使得一个导入中可以使用A.B.C目录路径语法。在A.B.C的一条导入中,名为A的目录位于相对于sys.path的常规模块导入搜索,B是A中的另一个包的子目录,C是一个模块或B中的其他可导入项。
    • 在一个包文件中,常规的import语句使用和其他地方的导入一样的sys.path搜索规则。包中导入使用from语句以及前面的点号,然而,它是相对于包的;也就是说,只检查包目录,并且不使用常规的sys.path查找。例如,from . import A中,模块搜索限制在包含了该语句中出现的文件的目录之中。

    最后,提一个问题:在什么情况下必须通过import而不能通过from使用包?

    只有在你需要读取定义在一个以上路径的相同变量名时,才必须通过import来使用包,而不能使用from。使用import,路径可以让引用独特化,然而,from却让任何变量名只有一个版本。

  • 相关阅读:
    Bump Mapping综述 (转)
    二进制表示(转)
    3D局部光照模型 (转)
    关于DEVMODE的数据结构显示设备的属性(转)
    The C++ Programming Language(一)
    The C++ Programming Language(二)
    linux_redhat9下安装FTP服务器
    oracle下用户相关问题整理
    Linux的基本命令学习与shell基本内容学习(2)
    winxp系统32位平台下利用oracle10g自带的DBCA(database configuration assistant)工具创建数据库
  • 原文地址:https://www.cnblogs.com/SsoZhNO-1/p/11402452.html
Copyright © 2011-2022 走看看