使用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下使用Psyco模块优化运行速度
Apr 05 Python
Python实现Youku视频批量下载功能
Mar 14 Python
Python设计实现的计算器功能完整实例
Aug 18 Python
解决python3 json数据包含中文的读写问题
May 10 Python
Flask框架配置与调试操作示例
Jul 23 Python
Python动态生成多维数组的方法示例
Aug 09 Python
python 搭建简单的http server,可直接post文件的实例
Jan 03 Python
python树莓派红外反射传感器
Jan 21 Python
在Django中预防CSRF攻击的操作
Mar 13 Python
python脚本和网页有何区别
Jul 02 Python
如何验证python安装成功
Jul 06 Python
Python 远程开关机的方法
Nov 18 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
弄了个检测传输的参数是否为数字的Function
2006/12/06 PHP
windows下配置apache+php+mysql时出现问题的处理方法
2014/06/20 PHP
从wamp到xampp的升级之路
2015/04/08 PHP
Yii核心验证器api详解
2016/11/23 PHP
php封装的mongodb操作类代码
2017/08/06 PHP
php面向对象重点知识分享
2019/09/27 PHP
php设计模式之组合模式实例详解【星际争霸游戏案例】
2020/03/27 PHP
PHP 对象继承原理与简单用法示例
2020/04/21 PHP
php判断数组是否为空的实例方法
2020/05/10 PHP
解析页面加载与js函数的执行 onload or ready
2013/12/12 Javascript
xmlhttp缓存清除的2种解决方法
2013/12/13 Javascript
判断复选框是否被选中的两种方法
2014/06/04 Javascript
JavaScript实现找出数组中最长的连续数字序列
2014/09/03 Javascript
jquery根据锚点offset值实现动画切换
2014/09/11 Javascript
javascript表格的渲染组件
2015/07/03 Javascript
JS区分浏览器页面是刷新还是关闭
2016/04/17 Javascript
JavaScript中的Reflect对象详解(ES6新特性)
2016/07/22 Javascript
基于Vue实现图书管理功能
2017/10/17 Javascript
微信小程序云开发实现数据添加、查询和分页
2019/05/17 Javascript
JavaScript面向对象程序设计中对象的定义和继承详解
2019/07/29 Javascript
vue 使用原生组件上传图片的实例
2020/09/08 Javascript
vue中如何添加百度统计代码
2020/12/19 Vue.js
python抓取网页图片示例(python爬虫)
2014/04/27 Python
Python动刷新抢12306火车票的代码(附源码)
2018/01/24 Python
Python Django 封装分页成通用的模块详解
2019/08/21 Python
python爬虫 正则表达式解析
2019/09/28 Python
浅谈pytorch、cuda、python的版本对齐问题
2020/01/15 Python
python3实现往mysql中插入datetime类型的数据
2020/03/02 Python
python使用Word2Vec进行情感分析解析
2020/07/31 Python
如何利用pycharm进行代码更新比较
2020/11/04 Python
通过代码简单了解django model序列化作用
2020/11/12 Python
莫斯科绝对前卫最秘密的商店:SVMoscow
2017/10/23 全球购物
关于元旦的广播稿
2014/02/16 职场文书
最经典的大学生职业生涯规划范文
2014/03/05 职场文书
节水倡议书范文
2014/04/15 职场文书
小兵张嘎观后感
2015/06/03 职场文书