使用Python的package机制如何简化utils包设计详解


Posted in Python onDecember 11, 2017

package 机制

package是模块的集合,每一个Package的根目录下面都应当有一个__init__.py 文件。当解释器发现目录下有这个文件时,他就会认为这是一个Package,而不是一个普通的目录。

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

简单来说,一个目录下如果包含 __init__.py ,则被 Python 视作一个 Python package。其中:

  • __init__.py 中的东西,在初始化这个包时,会首先被加载
  • package 中还可以定义 sub package

初衷

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

  • Library Author
  • Caller 即 API 使用者

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

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

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

然而大部分情况不是这样的,所有 Utils 都放到一个文件里面是 stupid 的(一个源码文件最多 400~500行 )。所以我们的目录结构会是这样的:

utils/
 __init__.py
 a_util.py
 b_util.py
 ......

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

这种方式有一个假定:调用者要很清楚他所需要的 Utils 位于哪个 py 文件中。但是这种假定并不总是成立,大家对于同一概念的理解,极有可能是千差万别的。比如 utils,你觉得叫做 utils 合适,别人还觉得叫做 tools 合适呢,其实都是同一个东西。

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

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 中都会写东西)

总结

以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作具有一定的参考学习价值,如果有疑问大家可以留言交流,谢谢大家对三水点靠木的支持。

Python 相关文章推荐
Python的SQLAlchemy框架使用入门
Apr 29 Python
python 类详解及简单实例
Mar 24 Python
Python中__slots__属性介绍与基本使用方法
Sep 05 Python
Python3.5 处理文本txt,删除不需要的行方法
Dec 10 Python
Python3使用TCP编写一个简易的文件下载器功能
May 08 Python
python文件选择对话框的操作方法
Jun 27 Python
Django中的cookie和session
Aug 27 Python
Python 迭代,for...in遍历,迭代原理与应用示例
Oct 12 Python
Django使用Celery加redis执行异步任务的实例内容
Feb 20 Python
Python Selenium 设置元素等待的三种方式
Mar 18 Python
python保留格式汇总各部门excel内容的实现思路
Jun 01 Python
Python - 10行代码集2000张美女图
May 23 Python
python timestamp和datetime之间转换详解
Dec 11 #Python
Python时间戳使用和相互转换详解
Dec 11 #Python
python的exec、eval使用分析
Dec 11 #Python
Python中eval带来的潜在风险代码分析
Dec 11 #Python
Python验证文件是否可读写代码分享
Dec 11 #Python
Python文件操作基本流程代码实例
Dec 11 #Python
Python使用Turtle模块绘制五星红旗代码示例
Dec 11 #Python
You might like
PHP中strtotime函数使用方法详解
2011/11/27 PHP
6种php上传图片重命名的方法实例
2013/11/04 PHP
PHP使用GD库输出汉字的方法【测试可用】
2016/11/10 PHP
PHP基于DateTime类解决Unix时间戳与日期互转问题【针对1970年前及2038年后时间戳】
2018/06/13 PHP
解决在Laravel 中处理OPTIONS请求的问题
2019/10/11 PHP
精选的10款用于构建良好易用性网站的jQuery插件
2011/01/23 Javascript
Jquery.addClass始终无效原因分析
2013/09/08 Javascript
parentElement,srcElement的使用小结
2014/01/13 Javascript
jquery通过ajax加载一段文本内容的方法
2015/01/15 Javascript
使用OpenLayers3 添加地图鼠标右键菜单
2015/12/29 Javascript
对Js OOP编程 创建对象的一些全面理解
2016/07/26 Javascript
基于JavaScript实现自定义滚动条
2017/01/25 Javascript
jquery中each循环的简单回滚操作
2017/05/05 jQuery
解决jQuery ajax动态新增节点无法触发点击事件的问题
2017/05/24 jQuery
vue component组件使用方法详解
2017/07/14 Javascript
vue组件实现可搜索下拉框扩展
2020/10/23 Javascript
vue实现多个元素或多个组件之间动画效果
2018/09/25 Javascript
关于element-ui的隐藏组件el-scrollbar的使用
2019/05/29 Javascript
vue 解决uglifyjs-webpack-plugin打包出现报错的问题
2020/08/04 Javascript
详解JavaScript的this指向和绑定
2020/09/08 Javascript
[03:51]吞吞映像 每周精彩击杀top10第二弹
2014/06/25 DOTA
Python中的条件判断语句与循环语句用法小结
2016/03/21 Python
Python实现的寻找前5个默尼森数算法示例
2018/03/25 Python
基于DataFrame改变列类型的方法
2018/07/25 Python
解决python web项目意外关闭,但占用端口的问题
2019/12/17 Python
python词云库wordcloud的使用方法与实例详解
2020/02/17 Python
django从后台返回html代码的实例
2020/03/11 Python
jupyter notebook运行命令显示[*](解决办法)
2020/05/18 Python
html5模拟平抛运动(模拟小球平抛运动过程)
2013/07/25 HTML / CSS
Html5原生拖拽相关事件简介以及基础实现
2020/11/19 HTML / CSS
一些.net面试题
2014/10/06 面试题
大四毕业生自荐书
2014/07/05 职场文书
征用土地赔偿协议书
2014/09/26 职场文书
卫生保健工作总结2015
2015/05/18 职场文书
有关三国演义的读书笔记
2015/06/25 职场文书
Python获取指定日期是"星期几"的6种方法
2022/03/13 Python