zoukankan      html  css  js  c++  java
  • 包是一种通过使用‘.模块名’来组织python模块名称空间的方式。

    1. 无论是import形式还是from...import形式,凡是在导入语句中(而不是在使用时)遇到带点的,都要第一时间提高警觉:这是关于包才有的导入语法

    2. 包是目录级的(文件夹级),文件夹是用来组成py文件(包的本质就是一个包含__init__.py文件的目录)

    3. import导入文件时,产生名称空间中的名字来源于文件,import 包,产生的名称空间的名字同样来源于文件,即包下的__init__.py,导入包本质就是在导入该文件

    强调:

      1. 在python3中,即使包下没有__init__.py文件,import 包仍然不会报错,而在python2中,包下一定要有该文件,否则import 包报错

      2. 创建包的目的不是为了运行,而是被导入使用,记住,包只是模块的一种形式而已,包即模块

    glance/                   #Top-level package
    
    ├── __init__.py      #Initialize the glance package
    
    ├── api                  #Subpackage for api
    
    │   ├── __init__.py
    
    │   ├── policy.py
    
    │   └── versions.py
    
    ├── cmd                #Subpackage for cmd
    
    │   ├── __init__.py
    
    │   └── manage.py
    
    └── db                  #Subpackage for db
    
        ├── __init__.py
    
        └── models.py

    注意事项


    1.关于包相关的导入语句也分为import和from ... import ...两种,但是无论哪种,无论在什么位置,在导入时都必须遵循一个原则:凡是在导入时带点的,点的左边都必须是一个包,否则非法。可以带有一连串的点,如item.subitem.subsubitem,但都必须遵循这个原则。

    2.对于导入后,在使用时就没有这种限制了,点的左边可以是包,模块,函数,类(它们都可以用点的方式调用自己的属性)。

    3.对比import item 和from item import name的应用场景:
    如果我们想直接使用name那必须使用后者。

    from ... import ...

    需要注意的是from后import导入的模块,必须是明确的一个不能带点,否则会有语法错误,如:from a import b.c是错误语法

    我们在与包glance同级别的文件中测试 

    1 from glance.db import models
    2 models.register_models('mysql')
    3 
    4 from glance.db.models import register_models
    5 register_models('mysql')

    __init__.py文件

    为了进一步的组织好模块,可以将它们分组为包。包基本上就是一类模块。当模块存储在文件中时,包就是模块所在的目录。为了能够让Python解释器将其作为包来对待,它必须包含一个命名为__init__.py的文件( __ init__.py 可以只是一个空文件,但是它也可以执行包的初始化代码,包括设置__all__变量等)。如果将它作为普通模块导入的话,文件的内容就是包的内容。

    下面是一个简单的包布局,包名为"drawing",其中包含名为"color"和"shapes"的模块:

    C:Python # 存放模块的路径
    C:Pythondrawing #包目录(drawing包)
    C:Pythondrawing\__init__.py # 包代码
    C:Pythondrawingcolors.py # colors模块
    C:Pythondrawingshapes.py # shapes模块

     配置好包之后,可以按照以下方式导入包的内容:

    # -- coding: utf-8 --
    import drawing # 导入drawing包
    import drawing.colors # 导入drawing包的colors模块
    from drawing import shapes # 导入drawing包的shapes模块

    from glance.api import *

    在讲模块时,我们已经讨论过了从一个模块内导入所有*,此处我们研究从一个包导入所有*。

    此处是想从包api中导入所有,实际上该语句只会导入包api下__init__.py文件中定义的名字,我们可以在这个文件中定义__all___:

    复制代码
    #在__init__.py中定义
    x=10
    
    def func():
        print('from api.__init.py')
    
    __all__=['x','func','policy']
    复制代码

     此时我们在于glance同级的文件中执行from glance.api import *就导入__all__中的内容(versions仍然不能导入)。

    glance/                   
    
    ├── __init__.py      
    
    ├── api                  
    
    │   ├── __init__.py   __all__ = ['policy','versions'] 
    
    │   ├── policy.py
    
    │   └── versions.py
    
    ├── cmd               __all__ = ['manage']    
    
    │   ├── __init__.py
    
    │   └── manage.py    
    
    └── db                __all__ = ['models']              
    
        ├── __init__.py
    
        └── models.py
    
    
    
    from glance.api import *
    policy.get()
    复制代码
    glance/                   
    
    ├── __init__.py      
    
    ├── api                  
    
    │   ├── __init__.py   __all__ = ['policy','versions'] 
    
    │   ├── policy.py
    
    │   └── versions.py
    
    ├── cmd               __all__ = ['manage']    
    
    │   ├── __init__.py
    
    │   └── manage.py    
    
    └── db                __all__ = ['models']              
    
        ├── __init__.py
    
        └── models.py
    
    
    
    from glance.api import *
    policy.get()
    复制代码

    绝对导入和相对导入

    我们的最顶级包glance是写给别人用的,然后在glance包内部也会有彼此之间互相导入的需求,这时候就有绝对导入和相对导入两种方式:

    绝对导入:以glance作为起始

    相对导入:用.或者..的方式最为起始(只能在一个包中使用,不能用于不同目录内)

    例如:我们在glance/api/version.py中想要导入glance/cmd/manage.py

    在glance/api/version.py
    
    #绝对导入
    from glance.cmd import manage
    manage.main()
    
    #相对导入
    from ..cmd import manage
    manage.main()

    测试结果:注意一定要在于glance同级的文件中测试

    1 from glance.api import versions 

    注意:在使用pycharm时,有的情况会为你多做一些事情,这是软件相关的东西,会影响你对模块导入的理解,因而在测试时,一定要回到命令行去执行,模拟我们生产环境,你总不能拿着pycharm去上线代码吧!!!

    特别需要注意的是:可以用import导入内置或者第三方模块(已经在sys.path中),但是要绝对避免使用import来导入自定义包的子模块(没有在sys.path中),应该使用from... import ...的绝对或者相对导入,且包的相对导入只能用from的形式。

    比如我们想在glance/api/versions.py中导入glance/api/policy.py,有的同学一抽这俩模块是在同一个目录下,十分开心的就去做了,它直接这么做

    1 #在version.py中
    2 
    3 import policy
    4 policy.get()

    没错,我们单独运行version.py是一点问题没有的,运行version.py的路径搜索就是从当前路径开始的,于是在导入policy时能在当前目录下找到

    但是你想啊,你子包中的模块version.py极有可能是被一个glance包同一级别的其他文件导入,比如我们在于glance同级下的一个test.py文件中导入version.py,如下

    from glance.api import versions
    
    '''
    执行结果:
    ImportError: No module named 'policy'
    '''
    
    '''
    分析:
    此时我们导入versions在versions.py中执行
    import policy需要找从sys.path也就是从当前目录找policy.py,
    这必然是找不到的
    '''
    glance/                   
    
    ├── __init__.py      from glance import api
                                 from glance import cmd
                                 from glance import db
    
    ├── api                  
    
    │   ├── __init__.py  from glance.api import policy
                                  from glance.api import versions
    
    │   ├── policy.py
    
    │   └── versions.py
    
    ├── cmd                 from glance.cmd import manage
    
    │   ├── __init__.py
    
    │   └── manage.py
    
    └── db                   from glance.db import models
    
        ├── __init__.py
    
        └── models.py
    glance/                   
    
    ├── __init__.py      from . import api  #.表示当前目录
                         from . import cmd
                         from . import db
    
    ├── api                  
    
    │   ├── __init__.py  from . import policy
                         from . import versions
    
    │   ├── policy.py
    
    │   └── versions.py
    
    ├── cmd              from . import manage
    
    │   ├── __init__.py
    
    │   └── manage.py    from ..api import policy   
                         #..表示上一级目录,想再manage中使用policy中的方法就需要回到上一级glance目录往下找api包,从api导入policy
    
    └── db               from . import models
    
        ├── __init__.py
    
        └── models.py

    单独导入包

    单独导入包名称时不会导入包中所有包含的所有子模块,如

    复制代码
    #在与glance同级的test.py中
    import glance
    glance.cmd.manage.main()
    
    '''
    执行结果:
    AttributeError: module 'glance' has no attribute 'cmd'
    
    '''
    复制代码

    解决方法:

    1 #glance/__init__.py
    2 from . import cmd
    3 
    4 #glance/cmd/__init__.py
    5 from . import manage

    执行:

    1 #在于glance同级的test.py中
    2 import glance
    3 glance.cmd.manage.main()

    千万别问:__all__不能解决吗,__all__是用于控制from...import * 

    import glance之后直接调用模块中的方法

    glance/                   
    
    ├── __init__.py     from .api import *
                        from .cmd import *
                        from .db import *    
    ├── api                  
    
    │   ├── __init__.py   __all__ = ['policy','versions'] 
    
    │   ├── policy.py
    
    │   └── versions.py
    
    ├── cmd               __all__ = ['manage']    
    
    │   ├── __init__.py
    
    │   └── manage.py    
    
    └── db                __all__ = ['models']              
    
        ├── __init__.py
    
        └── models.py
    
    
    import glance
    policy.get()
  • 相关阅读:
    洛谷—— P2234 [HNOI2002]营业额统计
    BZOJ——3555: [Ctsc2014]企鹅QQ
    CodeVs——T 4919 线段树练习4
    python(35)- 异常处理
    August 29th 2016 Week 36th Monday
    August 28th 2016 Week 36th Sunday
    August 27th 2016 Week 35th Saturday
    August 26th 2016 Week 35th Friday
    August 25th 2016 Week 35th Thursday
    August 24th 2016 Week 35th Wednesday
  • 原文地址:https://www.cnblogs.com/qunxiadexiaoxiangjiao/p/8288118.html
Copyright © 2011-2022 走看看