0. 前言
在几乎所有实践中,Python不可避免的需要导入其他模块,例如,当我们实践机器学习项目时,难免会在开头写到:
import numpy as np
在大多数时候,我们并不会仔细去思考他的运作方式,在许多教学视频或者书籍中,也不会仔细介绍import的逻辑。在代码量增大,或者是要发布/魔改package的时候,往往会出问题。下面就将总结import的几点机制,留作笔记之用。
1. Functions, Modules and Packages
Python是一门面向对象的编程语言,“模块化”贯穿了整个Pythonic思想,而函数、模块和包在Python之中起着举足轻重的作用。
简单地讲:
一段能够执行某个功能的代码皆可以称之为函数;
模块是函数的集合;
包是模块的集合。
特此说明,这样说并不严谨,例如模块甚至可以是Cython或纯粹C语言所写;包也可以包含子包。
2. Import速览
import_stmt ::= "import" module ["as" identifier] ("," module ["as" identifier])*
| "from" relative_module "import" identifier ["as" identifier]
("," identifier ["as" identifier])*
| "from" relative_module "import" "(" identifier ["as" identifier]
("," identifier ["as" identifier])* [","] ")"
| "from" relative_module "import" "*"
module ::= (identifier ".")* identifier
relative_module ::= "."* module | "."+
以上摘自官方文档
简单来说,可以不严谨的描述为
[from] [packge|module] import module [as] [alias]
[ ]中为可选项
examples:
均以使用zeros函数为例
import numpy #numpy.zeros()
import numpy as np #np.zeros()
from numpy import zeros,eye #zeros(),逗号可以Import多个
from numpy import * #zeros()
03. Import逻辑探析
02章节中介绍的是基本用法,但在深层次的应用上往往会有更细节的情况。
例如,偶尔会有人问到:from …module import xxx是什么意思?Python中from 省略号/点点 Import …是什么意思?
from ..utils import Padding
from myutils.utils import Padding
首先是import的逻辑:
- 为了减少开销,Import会首先搜索模块缓存。
- 然后会搜索内置模块列表
- 最后会搜索sys.path
sys.path:
A list of strings that specifies the search path for modules. Initialized from the environment variable PYTHONPATH, plus an installation-dependent default.
- 找不到时抛出错误。
from的逻辑:
from的逻辑与Import类似,只是多一个搜索绑定的过程。
值得一提的是,PEP8推荐的是绝对引用,虽然绝对引用可能对开销来说更加友好,但也许会对我们人类自己造成一些困难。例如:
from transfomer.tokenlizer.wordpiece.unigram import is_sp_token
这样的代码段太冗长了,并且,我个人在阅读部分知名开源库的时候,发现更常用的往往是相对引用。
例如前文所述的
from ..utils import Padding
这里的”.”,并不是省略号,而是“点”(dot),是上古先贤们传下来的文化传统。
对于当前位置而言,
一个点代表处于同级目录,
两个点代表处于父目录,
三个点代表处于祖父目录…
04. 小结
虽然很多实践还是相对引用得多,
但代码看多了还是觉得绝对引用比较好,
毕竟是PEP8