ICode9

精准搜索请尝试: 精确搜索
首页 > 编程语言> 文章详细

python之包

2021-04-14 21:58:05  阅读:201  来源: 互联网

标签:__ __. 之包 python py init 导入 import


python之包

文章目录

一、包的介绍

# 官网解释
Packages are a way of structuring Python’s module namespace by using “dotted module names”
包是一种通过使用‘.模块名’来组织python模块名称空间的方式。

什么是包?

  • 包就是一个超级模块,是用来被导入使用的

  • 具体来说:包就是一个包含有__init__.py文件的文件夹

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

包的本质

python包的目的不是为了运行的。而是被导入使用的, 被导入和被右键运行是截然不同的两件事,包是模块的一种形式,换句话说包的本质就是一种模块。

为什么要用包?

包存在的意义:

  • 因为你作为模块的设计者到你的模块越来越多,你要很好的去管理你的功能,你要需要放分文件管理。把你一个一个文件去组织起来。可以把python的一堆模块丢进去,包的用途就是就是被导入的.

  • 其中 包下面所有的文件夹和文件也包括包自己都是用来被导入的。有了包这个概念以后你就掌握了一种能够把多个python模块给组织到一个文件夹里面放着的这种解决方案,以此来提供程序的结构性和可维护性

  • 包就是一个文件夹,将文件夹唯一的功能就是将文件组织起来

示例:

pool/                #顶级包
├── __init__.py     
├── futures          #子包
│   ├── __init__.py
│   ├── process.py
│   └── thread.py
└── versions.py      #子模块

包下面的 __init__.py 文件介绍

包下面的__init__.py存在的意义:

当你在运行文件夹的时候,有一个文件可以代替运行。这就是包下的__init__.py文件所存在的一样意义。

python3中与python2中的__init__.py存在的必要性:

你需要考虑的是,如果下面存放了好多模块,当然每个模块都应该有自己自己的名字。我们需要把这些名字拿到__init__.py里面, 才能使用。python3中即便没有这个__init__.py文件也不会报错,pyhon2二中就会报错。所以在python2中必须要有__init__.py这个文件。

二、使用包的注意事项

  • 包的导入和模块导入一样,使用语句from...import 和 import

  • 导入时带点 : . 的, 点的左边必须是一个包, 否则非法, 可以带有一连串的点, 这是导入包特有的语法

    关于包相关的导入语句也分为import和from ... import ...两种,但是无论哪种,无论在什么位置,在导入时都必须遵循一个原则:凡是在导入时带点的,点的左边都必须是一个包,否则非法。可以带有一连串的点,如import 顶级包.子包.子模块,但都必须遵循这个原则。但对于导入后,在使用时就没有这种限制了,点的左边可以是包,模块,函数,类(它们都可以用点的方式调用自己的属性)。
    
  • 使用 from...import 导入时, import后面必须是一个明确的名字, 不能有任何的前缀

  • 导入包的本质就是导入__init__.py文件

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

    包A和包B下有同名模块也不会冲突,如A.a与B.a来自俩个命名空间
    

三、导入包发生的三件事

  • 产生一个包的名称空间
  • 触发包下的__init__.py文件的运行,产生一个__init__.py的名称空间,将运行__init__.py文件过程中产生的名字存放于包的名称空间中
  • 在当前执行文件中拿到一个名字包文件夹名,该名字指向包的名称空间
# 假设我创建一个名为 "aaa" 的包
import aaa   # 导入包 "aaa"

print(aaa.x)  # "aaa.x"就是向 "__init__.py" 要一个名字 "x"

四、绝对导入与相对导入

绝对导入

  • 包里面的导入都是包内模块之间的相互导入, 不是用来执行的
  • 绝对导入都是以包的顶级路径作为起始点
  • 绝对导入没有任何限制, 是通用的一种导入方式

一层包示例

'''
包/                    
├── aaa/          # 顶级包
│   ├── __init__.py
│   ├── xxx.py	#子模块
│   └── yyy.py	#子模块
└── run.py      # 执行程序
'''

# "__init__.py" 内容
print("i am aaa.__init__")  # 包被导入就会被执行

from aaa.xxx import f1
from aaa.yyy import f2

# "xxx.py" 内容
def f1():
    print("i am xxx")
    
# "yyy.py" 内容
def f2():
    print("i am yyy") 
   
# "run.py" 内容  # 执行文件
import aaa

aaa.f1()
aaa.f2()
''' 执行结果
i am aaa.__init__
i am xxx
i am yyy
'''

二层包示例

'''
包/   
├── aaa         #顶级包
│   ├── __init__.py
│	├── bbb          # 子包
│ 	│   ├── __init__.py
│ 	│   └── zzz.py 	# 子模块
│  	└── xxx.py      # 子模块
│	└── yyy.py      # 子模块
└── run.py      #执行程序
'''
# "aaa"下"__init__.py" 内容
from aaa.xxx import f1
from aaa.yyy import f2
from aaa.bbb.zzz import f3

# "xxx.py" 内容
def f1():
    print("i am f1")
    
# "yyy.py" 内容
def f2():
    print("i am f2")

# "bbb"下"__init.py" 内容
from aaa.bbb.zzz import f3

# "zzz.py" 内容
def f3():
    print("i am f3")
    
# "run.py"  内容  # 执行文件
import aaa

aaa.f1()   # 没有改变用户的调用方式
aaa.f2()   
aaa.f3()
''' 执行结果
i am f1
i am f2
i am f3
'''

相对导入

  • 相对导入只能使用 from...import..., 使用 import .f1报错
  • . 代表当前文件所在的目录, .. 代表当前文件的上一级目录, ... 以此类推
  • 相对导入不能跨出包, (就是不能...点出了顶级包), 仅限于包内模块的相对导入
  • 针对包内部模块之间的相互导入, 推荐使用相对导入

示例:

'''
包/                 
├── mmm/          # 顶级包
│   ├── __init__.py
│   ├── m1.py	#子模块
│   ├── m2.py	#子模块
│   └── m3.py	#子模块
└── run.py      # 执行程序
'''
# "__init__.py"  内容
from .m1 import f1
from .m2 import f2
from .m3 import f3

# "m1.py"  内容
def f1():
    print("i am m1.f1")
    
# "m2.py"  内容
def f2():
    print("i am m2.f2")
    
# "m3.py"  内容
def f3():
    print("i am m3.f3")
    
# "run.py"  内容
import mmm

mmm.f1()   # 使用者调用方式不变
mmm.f2()
mmm.f3()
'''  执行结果
i am m1.f1
i am m2.f2
i am m3.f3
'''

五、绝对导入与相对导入总结

绝对导入

  • 以执行文件的 sys.path 为起始点开始导入
  • 优点 : 执行文件与被执行的文件中都可以使用
  • 缺点 : 所有的导入都是以 sys.path 为起始点, 导入麻烦

相对导入

  • 参照当前所在文件的文件夹为起始点开始查找
  • 优点 : 导入更加简单
  • 缺点 : 只能在包内模块相互导入时才能使用

六、from…import *

  • * 代表导入所有
  • 可以使用 __all__=["xxx","yyy"] 来控制能使用的模块
  • __all__ 是在 __init__.py 文件下定义的

ps : 用户无法区分模块是文件还是一个包,我们定义包是为了方便开发者维护

标签:__,__.,之包,python,py,init,导入,import
来源: https://blog.csdn.net/weixin_44621343/article/details/115710376

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有