利用 Python 的 package 机制简化 utils 包设计

package 机制

对于 package 机制的说明,其实官方文档已经有很是详尽的论述了,本文并不着眼于此。bash

简单来讲,一个目录下若是包含 __init__.py ,则被 Python 视做一个 Python package。其中:优化

  1. __init__.py 中的东西,在初始化这个包时,会首先被加载
  2. package 中还能够定义 sub package

初衷

为了概念统一,咱们把写代码的人,大体分为两种角色:spa

  1. Library Author
  2. Caller 即 API 使用者

有时候咱们会是 1 或者 2, 有时候咱们可能既是 1 又是 2 ( 好比负责一个较大的系统时)code

很显然,本文的角度是从 1 出发的(即咱们只扮演库做者,而且不知道咱们的调用者是谁)。文档

最开始时,utils 可能仅仅是一个 utils.py 就能够了,而后调用者 from utils import XXUtils 就完事了,这天然没有本文什么事。源码

然而大部分状况不是这样的,全部 Utils 都放到一个文件里面是 stupid 的(一个源码文件最多 400~500行 )。因此咱们的目录结构会是这样的:it

utils/
    __init__.py
    a_util.py
    b_util.py
    ......
复制代码

调用者怎么使用呢?from utils.a_util import AUtilsio

这种方式有一个假定:调用者要很清楚他所须要的 Utils 位于哪一个 py 文件中。可是这种假定并不老是成立,你们对于同一律念的理解,极有多是千差万别的。好比 utils,你以为叫作 utils 合适,别人还以为叫作 tools 合适呢,其实都是同一个东西。class

显然,这加剧了调用者的心智负担。更加显然的是,做为库做者,咱们有义务来优化调用者的使用体验!(否则你的库再牛逼,没有人爱用也是空弹琴。)import

HOW

合理利用 package 机制,就能立刻优化这一体验。

咱们只要在 __init__.py 中这么写便可:

__init__.py

from .a_util import AUtils
from .b_util import BUtils
复制代码

调用者则仍然是这么使用:

from utils import AUtils, BUtils
复制代码

即:调用者根本不关心你的实如今哪里,你只要给我一个 utils 的命名空间便可,并且确保全部的 Utils 都在这个命名空间里面。

为了更加符合 PEP8 的规范,做为库做者,咱们的目录结构可能会变成这样:

utils/
    __init__.py
    _a_util.py               不对外界公开, 仅限本package的其余模块使用
    _b_util.py
复制代码

应用

不只是对于 utils 包,对与 constants 包,exceptions 包也能够应用此方法。在许多开源库中,大牛们常常使用这一手法来优化咱们的体验(太常见了,几乎大部分开源库的 __init__.py 中都会写东西)

相关文章
相关标签/搜索