Python3.7中一种懒加载的方式

2018 年 4 月 27 日 Python程序员

Python部落组织翻译,欢迎转发,禁止转载


注意:这篇博文中的代码,现在已经是PyPI上modutil模块的一部分了。


Python3.7在模块上也添加了__getattr__()和__dir__()两个方法。这个新特性让我们能够实现一些有趣的事情。例如,通过定义__dir__方法,你可以要求dir(模块)只显示__all__中定义的内容了。


但对于我来说,我更关心__getattr__方法,以及我如何能利用这个特性实现懒加载。在本文的开始,我希望先告诉大家,大多数人的代码是不需要懒加载的。只有当懒加载带来的好处很有用时你才应该使用它,比如,一个运行时间很短的终端程序。对于大多数人,懒加载都是没有必要的,甚至是有害的,它会让你延后得知导入失败,而不是项目一启动时就能够知道。


旧方法


之前我们有两种方式做懒加载。最古老的方式是在局部加载,而不是全局加载(例如在你定义的函数内进行导入,而不是在模块顶部进行导入)。这种方式确实推迟了加载的时间点,在你的函数被运行时,函数里的import语句才会进行真正的加载。但它有一个缺点就是,这个import语句需要在不同的函数中写很多次。而且由于你只是在一些函数中写了import语句,你很可能写着写着就忘记了想要规避哪个模块的全局引用,然后后面又不小心全局引用了同样的模块。这个做法确实能实现懒加载,就是写法不够好。

另一种方法是使用importlib中提供的延迟加载器。Google、Facebook和Mercurial的很多开发者在使用这个延迟加载器。Google和Facebook主要是看中这个方法性能不错,Mercurial主要是看中这个方法比较简单、开发迅速。使用这个延迟加载器有一个很好的效果,它会提前检查要导入的模块是否能找到,如果找不到会抛出一个ModuleNotFoundError错误,而真正被延迟的只是模块加载的过程。


很多人很喜欢这个延迟加载器,以至于他们让所有的东西都延迟加载了。这样做有优点也有缺点。优点是你没有额外付出什么努力,就让所有的模块都延迟加载了。缺点是因为你让模块默认延迟加载了,会导致一些需要即时加载的模块的逻辑发生错误(这也就是Python箴言中为什么说明确优于隐晦)。事实上,Mercurial为了避免这个问题,专门维护了一个模块黑名单,黑名单上的模块不进行延迟加载。但为此,他们不得不一直维护这个名单,所以这样做也不是一个很好的办法。


新方法


在Python3.7中,模块上可以定义一个__getattr__方法,这让开发者可以定义一个函数,使得访问的模块属性不存在时,导入一个模块作为当前模块的属性。这样做确实也有“发现导入错误被推迟”这个弊病,但是由于你的导入还是全局的,所以代码更容易控制。


这个代码本身并不复杂。

你可以这样使用上面的代码

设计这个函数时,最棘手的部分就是模拟import ... as ... 语法来避免命名冲突,我最终选择使用一个类似原有as语法的字符串。我也可以把as语法字符串再拆分为第三个参数,这个参数也是一个字典对象,但是我想没必要这样做,能与原有语法有更多的相同点,当然是最好的。


无论如何,这个思考的过程都让我很享受。我喜欢这种用20行Python代码就完成一个不错的功能的感觉!


译者:诗书塞外

英文原文:https://snarky.ca/lazy-importing-in-python-3-7/

登录查看更多
3

相关内容

Python是一种面向对象的解释型计算机程序设计语言,在设计中注重代码的可读性,同时也是一种功能强大的通用型语言。
【实用书】Python技术手册,第三版767页pdf
专知会员服务
227+阅读 · 2020年5月21日
【干货书】流畅Python,766页pdf,中英文版
专知会员服务
223+阅读 · 2020年3月22日
【书籍推荐】简洁的Python编程(Clean Python),附274页pdf
专知会员服务
171+阅读 · 2020年1月1日
Python 3.8.0来了!
数据派THU
5+阅读 · 2019年10月22日
GitHub 热门:各大网站的 Python 爬虫登录汇总
机器学习算法与Python学习
9+阅读 · 2019年3月20日
Python3.8新特性概览
Python程序员
4+阅读 · 2018年12月8日
Python | Jupyter导出PDF,自定义脚本告别G安装包
程序人生
7+阅读 · 2018年7月17日
Python 杠上 Java、C/C++,赢面有几成?
CSDN
6+阅读 · 2018年4月12日
快乐的迁移到 Python3
Python程序员
5+阅读 · 2018年3月25日
为什么你应该学 Python ?
计算机与网络安全
4+阅读 · 2018年3月24日
教你用Python来玩跳一跳
七月在线实验室
6+阅读 · 2018年1月2日
Python & 机器学习之项目实践 | 赠书
人工智能头条
12+阅读 · 2017年12月26日
Arxiv
7+阅读 · 2019年5月31日
Embedding Logical Queries on Knowledge Graphs
Arxiv
3+阅读 · 2019年2月19日
VIP会员
相关资讯
Python 3.8.0来了!
数据派THU
5+阅读 · 2019年10月22日
GitHub 热门:各大网站的 Python 爬虫登录汇总
机器学习算法与Python学习
9+阅读 · 2019年3月20日
Python3.8新特性概览
Python程序员
4+阅读 · 2018年12月8日
Python | Jupyter导出PDF,自定义脚本告别G安装包
程序人生
7+阅读 · 2018年7月17日
Python 杠上 Java、C/C++,赢面有几成?
CSDN
6+阅读 · 2018年4月12日
快乐的迁移到 Python3
Python程序员
5+阅读 · 2018年3月25日
为什么你应该学 Python ?
计算机与网络安全
4+阅读 · 2018年3月24日
教你用Python来玩跳一跳
七月在线实验室
6+阅读 · 2018年1月2日
Python & 机器学习之项目实践 | 赠书
人工智能头条
12+阅读 · 2017年12月26日
Top
微信扫码咨询专知VIP会员