包及绝对,相对导入

概要:

什么是模块
    一系列功能的集合
    一堆函数放在一个py文件
为什么用模块
    提高维护性,可读性,减少代码冗余,使代码组织结构更清晰
四种分类:
    1.自定义,包括第三方
    2.内置的
    3.DLL的c或C++
    4.包
如何使用:
    import
        1.创建名称空间
        2.执行模块文件
        3.在执行文件中创建一个名称 指向模块的名称空间
    from
        1.创建名称空间
        2.执行模块文件
        3.把模块中的名称复制到当前名称空间
    两种的区别在于第三步
    import m1
    m1.func1()

    from m1 import func1
    func1()
    注意:避免名称冲突
模块搜索顺序
    内存已经加载的 - > 内置的 -> sys.path
    sys.modules可用查看内存已经加载的
    我们经常会操作的是sys.path
两种执行方式:
    1.作为执行文件
    2.作为模块被导入使用
    在代码中可用使用__name__来区分

包
   是包含一堆模块的文件夹
   本质上就是一个文件夹
   不同的是 包中应该包含__init__.py文件
为什么使用包?:
    从文件夹级别来组织代码

如何使用:
    与使用模块一样

    注意:在导入一个包时 实际上导入的是__init__.py

init的作用
    用于初始化包中的模块
    init中主要做什么?
        导入包中的模块
包的嵌套
    包里面还有包

绝对导入
    以执行文件的sys.path为起始点

相对导入
    相对于某个模块而言,参照当前所在文件的文件夹为起始开始查找
    .表示当前文件  ..表示上一级 ...再上一级
    注意:相对导入仅用于包内模块的相互导入
        不能超过顶层包
        from 导入时 .点的左边必须是一个包名
        import 后面必须是一个明确的名字

1.什么是包概念:

     包,也是一种模块,对于使用者而言,使用方式和模块没有任何区别。

  本质上就是一个文件夹,不同之处在于:多了一个__init__.py文件,叫包的初始化 文件

2.为什么要使用包:

包的本质就是一个文件夹,那么文件夹唯一的功能就是将文件组织起来
随着功能越写越多,我们无法将所以功能都放到一个文件中,于是我们使用模块去组织功能,而随着模块越来越多,我们就需要用文件夹将模块文件组织起来,以此来提高程序的结构性和可维护性

3.如何使用包:

  import 导入模块时发生了三件事情

  1.创建名称空间

  2.执行模块py文件,加载名称

  3.在执行文件中产生新的名称,指向模块

  在导入包的时候,由于包实际上是一个文件夹,所以包中需要提供__init__.py文件,该文件用于代表这个包。

所以import pack,实际是执行了pack下的__init__.py导入这个名称

 __init__.py文件的作用

  导入该包下的所有模块,这样一来使用包的人,用起来非常简单,无需关心包中的文件结构,只要导入了包,就能使用包中所有功能。

  __init__.py文件应该包含哪些内容?

  不应该包含任何的业务逻辑,仅仅用于导入包中的模块

注意:所有文件的模块导入都以执行文件sys.path为准

#1.关于包相关的导入语句也分为import和from ... import ...两种,但是无论哪种,无论在什么位置,
  在导入时都必须遵循一个原则:凡是在导入时带点的,点的左边都必须是一个包,否则非法。可以带有一连串的点,如item.subitem.subsubitem,但都必须遵循这个原则。
                但对于导入后,在使用时就没有这种限制了,点的左边可以是包,模块,函数,类(它们都可以用点的方式调用自己的属性)。
#2、import导入文件时,产生名称空间中的名字来源于文件,import 包,产生的名称空间的名字同样来源于文件,即包下的__init__.py,导入包本质就是在导入该文件 #3、包A和包B下有同名模块也不会冲突,如A.a与B.a来自俩个命名空间

 导入包:

import

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

#在与glance同级的test.py中
import glance
glance.cmd.manage.main()  #main方法在manage模块中

'''
执行结果:报错
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()

from ... import ...

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

1 from glance.db import models-->这是个模块
2 models.register_models('mysql')
3 
4 from glance.db.models import register_models-->这是个函数
5 register_models('mysql')

 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是写给别人用的,然后在glance包内部也会有彼此之间互相导入的需求,这时候就有绝对导入和相对导入两种方式:

  绝对导入:以执行文件的sys.path作为起始点(执行文件只能用绝对导入

    优点:执行文件和被导入的模块中(被导入的模块中可能也会导入别的模块)都可以使用

    缺点:所有导入都是以sys.path为起始点,导入麻烦

  相对导入:参照当前所在文件的文件夹为起始开始查找(只能在一个包中使用,不能用于不同目录内)

    符号:.代表当前所在文件的文件夹,..代表上一级文件夹,...代表上上一级文件夹

    优点:导入更加简单

    缺点:只能在被导入的模块中使用,不能在执行文件中用,执行文件同级可能有很多文件,导致查找效率低.而包内文件有限,不会存在查找效率问题

  例如:我们在glance/api/version.py中想要导入glance/cmd/manage.py  #cmd和api属于两个并列文件夹

1 在glance/api/version.py中
2 
3 #绝对导入
4 from glance.cmd import manage
5 manage.main()
6 
7 #相对导入
8 from ..cmd import manage
9 manage.main()

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

1 from glance.api import versions 
posted @ 2018-10-12 20:22  ChuckXue  阅读(206)  评论(0编辑  收藏  举报