python之包
作者:互联网
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