模块与包
# 内置函数
这个部分主要是做做笔记,将每个函数对应的功能记下
# 包
### 包是什么:
包是一种模块 但本质上就是一个文件夹
与普通文件夹的区别就是其中包含一个init文件
### 包的作用
包的作用就是从文件夹级别组织代码
目的是为了提高维护性
### 什么时候应该使用包
之前我们将代码抽取到模块中 从文件级别组织代码 但是如果模块比较多的情况下 结构依然混乱
此时我们就需要使用包来组织代码
### 包的使用
创建一个包
右键 new -> python package
使用包
既然包也是模块 那么使用方式就是一样的 使用import来导入包
import 包名
### init文件的作用
##### 思考在导入包时发生了什么?
我们说包也是一种模块 所以内部原理是一样的
1.创建名称空间
2.执行模块中的代码
3.在执行文件中产生名称指向模块名称空间
但是现在包他是一个文件件不是一个py文件那么第二步该怎么执行呢?
这时候__init__.py就派上用场了
在导入包时 实际上执行的就是这个__init__文件
##### 好处
如此一来我们可以使用init来把一个文件夹变成一个模块 这个模块的种类是包
通常情况下 一个包中有多个 模块 并且这些模块经常会同时被导入使用
这时候你可以在init中将需要的模块一次性导入 当外界在使用这个包的时候 就无需再挨个导入了
##### 总结
init的作用是初始化包 初始化其实就是将包中需要提供给外界的模块统一导入 打包在一起
用户导入了包 就能使用所有的功能
##### 注意
init 导入模块文件时 由于是作为模块导入 所以sys.path中并不包含 模块所在目录 所以应该导入时要指定包名
```python
pack包下的init
from pack import module
import pack.module
```
##### 另外
init文件 在python2中是必须的 python3中可选的 但是建议都要有 规范
### 包的嵌套
##### 定义:包中有包如下
要使用子包中的内容 方法一致 在子包中的init中导入需要的内容 但是注意 不管是不是子包 都是作为模块导入
所以sys.path中肯定不包含子包路径 导入时需要从执行文件目录往下找
```python
subpack包下的 init文件
import pack.subpack.module4
```
### 导入包时的注意事项
使用import导入模块时 可以加点来访问下一层
```python
import pack.subpack.module4
```
==注意 点的左边必须是包名或是模块名==
我们也可以使用from来导入
```python
from pack.subpack import module4
```
==注意 import后面的内容不可以包含点 必须是一个明确的名字==
### 练习
作为一个模块的开发者 提供一个模块 给大家使用
随着时间的推移你的模块中的功能越来越多 管理变得困难
于是采取分模块的方式
但是一旦分文件 将导致用户的调用方式发生改变 用户需要从新学习新的使用方式
现在你的面临的问题是 如何能够使自己管理代码变得方便 并且不变更用户的调用方式
解决的方案就是 使用包 并在init文件中 导入所有功能
#### ==所以包的终极奥义就是将一堆模块中的功能集中到一个文件中 方便开发者管理代码 方便使用者调用功能==
### 相对导入与绝对导入
利用上面的例子 我们继续来思考
很多时候一个包内的模块需要相互调用对方的功能来完成操作
按照我们之前的导入方式 从执行文件开始一层一层往下找是可以的
但是一个问题是如果包的层级较多 你的导入语句会很长
另一个问题 如果我们后期需要修改包的名称 那你需要将每一个导入语句都进行修改
来看一下例子:
我们可以使用相对导入的方式来简化书写并提高我们的代码的扩展性
##### 注意
**相对导入仅能用于模块之间互相导入 不能用于执行文件中**
##### 常见错误演示
1.绝对导入时没有从执行文件目录开始
2.在执行文件中使用相对导入
3.跳出顶层包
```python
ValueError: attempted relative import beyond top-level package
```