python 是通过module组织代码的,每一个module就是一个python文件,但是modules是通过 package 来组织的。
package 的定义很简单,在当面目录下有 __init__.py
文件的目录即为一个 package 。
不管 __init__.py
是空的还是有内容的,这个目录都会被认为是一个 package ,这是一个标识。
Python 的 package 以及 package 中的 __init__.py
共同决定了 package 中的 module 是如何被外界访问的。
__init__.py
内的导入顺序这个在解决重写的问题时会很有用,探究过程就如这篇博客所说的,这里只放结论。
检查顺序如下:
__init__.py
文件内变量__init__.py
的写法这个文件本质上和我们平常写的python文件没有太大的区别,但是要注意两点:
__init__.py
轻量化,最小化其中代码的副作用,最好全部打包成函数。__init__.py
的时候暴露出来,这样在其他地方的引用就不需要引用具体位置,只需要引用这个包就好了。跳转链接: 使用自定义的 package
下面这个原先的版本应该是 python 2 的,python 3 完全不同了,所以进行了一些删减,仅仅作为小知识点。
到这里我们想到的第一件事情就是把我们的元素都导入,于是我们就想到使用:
from module import *
因为 *
实在是范围太广了,那么如何决定哪些是可以导入的呢?这里我们引入变量 __all__
。
__all__
是 __init__.py
文件中的一个列表型变量,通过定义 __all__
我们可以规定 from module import *
可以导入的元素有哪些。我们只需要在 __init__.py
中添加一行代码:
__all__ = ["module0", "moduole1", "module2", ···]
之后Python会按顺序逐一导入列表中的元素。
这个就很直接了,我们不使用 *
就一个一个得导入。
导出将按照以下规则执行:
__init__.py
中可被执行的代码__init__.py
中定义的 variable 被导入所以也可以侧面反应我们的 __all__
变量的作用是怎样的了。能够节省一定的时间。
首先随着项目的变大,通过 package 来整理项目变得尤为重要。
Python 是通过 module 组织代码的,module 即一个 py 文件,module 又是通过 package 来组织的, package 是一个包含 __init__.py
的文件夹,代码,module, package 它们三者的关系就是:module 包含代码, package 至少包含一个为 __init__.py
的 module。
这中间没有 class 的概念,class 更多是面向对象的时候使用的,可以作为 module 中的一个元素。
跳转链接:init.py 的写法
这里有一个盲区,我们在使用 package 的时候往往不会放在某一个特定的仓库,只有完全标准化之后的 package 才会放到某一个地方保存好。
问题就来了,我们的工作目录往往不在系统路径下,也就是说没有把当前工作路径添加到System Variable Path。我们无法直接调用同一目录下的 package 。
所以我们需要做的事情是添加一个临时的系统路径,在import之前添加上这个系统路径。
import sys
sys.path.append("upper folder of the package ")
这里我们需要把目标pakage的上层目录添加进path中,这样我们才能找到这个 package 。
如果我们的自定义 package 和 main.py
有相同的系统里路径,那就简单多了。
import sys, os
sys.path.append(os.getcwd())
然后我们有两种使用自定义 package 的方式如下所示。
这种就是比较直接的方法,我们在 main.py
中添加每一个 package 或者 subpackage 的路径,然后直接 import 进来。
代码举例:
# we assume that the DIY package is under cwd
import sys, os
sys.path.append(os.path.join(os.getcwd(), ' package 0', ' package 1'))
sys.path.append(os.path.join(os.getcwd(), ' package 0', ' package 2'))
import package 0. package 1.module0
import package 0. package 2.module1
这个如果要分类的话属于递归调用的方法,我们在每一层的 __init__.py
将路径临时添加进path中,保证了只要我们的最外层 package 的在path中了,我们剩下的 subpackage 都可以被索引到。
因此我们不需要再对我们的 main.py
做任何修改了。我们需要做的事情只有在每一个 __init__.py
中添加一层当前文件夹。
具体代码如下:
import sys, os
sys.path.append(os.path.join(os.getcwd(), 'subpackage '))
from subpackage import *
阅读 __init__.py
源码后发现大家写得都不太一样。但是相信基本思想就这些了,应该出入不大了。
python中 r'string'
,b'string'
,u'string'
,f'string'
的含义:
字符 | 含义 |
---|---|
r/R | 非转义的原始字符串 |
b | bytes |
u/U | 表示unicode字符串 |
f/format() | 格式化操作 |