Python __init__.py文件的作用
我们经常在python的模块目录中会看到 "__init__.py" 这个文件,那么它到底有什么作用呢?
1. 模块包(module package)标识
如果你是使用python的相关IDE来进行开发,那么如果目录中存在该文件,该目录就会被识别为 module package 。
2. 控制导包范围
假设我们的模块包的目录结构如下:

.
└── mypackage
├── subpackage_1
│ ├── test11.py
│ └── test12.py
├── subpackage_2
│ ├── test21.py
│ └── test22.py
└── subpackage_3
├── test31.py
└── test32.py

如果我们使用最直接的导入方式,将整个文件拷贝到工程目录下,然后直接导入:

from mypackage.subpackage_1 import test11
from mypackage.subpackage_1 import test12
from mypackage.subpackage_2 import test21
from mypackage.subpackage_2 import test22
from mypackage.subpackage_3 import test31
from mypackage.subpackage_3 import test32

当然这个例子里面文件比较少,如果模块比较大,目录比较深的话,可能自己都记不清该如何导入。(很有可能,哪怕只想导入一个模块都要在目录中找很久)
这种情况下,__init__.py 就很有作用了。我们先来看看该文件是如何工作的。
2.1 __init__.py 是怎么工作的?
实际上,如果目录中包含了 __init__.py 时,当用 import 导入该目录时,会执行 __init__.py 里面的代码。
我们在mypackage目录下增加一个 __init__.py 文件来做一个实验:

.
└── mypackage
├── __init__.py
├── subpackage_1
│ ├── test11.py
│ └── test12.py
├── subpackage_2
│ ├── test21.py
│ └── test22.py
└── subpackage_3
├── test31.py
└── test32.py

mypackage/__init__.py 里面加一个print,如果执行了该文件就会输出:
print("You have imported mypackage")
下面直接用交互模式进行 import
>>> import mypackage
You have imported mypackage
很显然,__init__.py 在包被导入时会被执行。
2.2 控制模块导入
我们再做一个实验,在 mypackage/__init__.py 添加以下语句:
from subpackage_1 import test11
我们导入 mypackage 试试:

>>> import mypackage
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "/home/taopeng/Workspace/Test/mypackage/__init__.py", line 2, in <module>
from subpackage_1 import test11
ImportError: No module named 'subpackage_1'

报错了。。。怎么回事?
原来,在我们执行import时,当前目录是不会变的(就算是执行子目录的文件),还是需要完整的包名。
from mypackage.subpackage_1 import test11
综上,我们可以在__init__.py 指定默认需要导入的模块
2.3 偷懒的导入方法
有时候我们在做导入时会偷懒,将包中的所有内容导入
from mypackage import *
这是怎么实现的呢? __all__ 变量就是干这个工作的。
__all__ 关联了一个模块列表,当执行 from xx import * 时,就会导入列表中的模块。我们将 __init__.py 修改为 。
__all__ = ['subpackage_1', 'subpackage_2']
这里没有包含 subpackage_3,是为了证明 __all__ 起作用了,而不是导入了所有子目录。

>>> from mypackage import *
>>> dir()
['__builtins__', '__doc__', '__loader__', '__name__', '__package__', '__spec__', 'subpackage_1', 'subpackage_2']
>>>
>>> dir(subpackage_1)
['__doc__', '__loader__', '__name__', '__package__', '__path__', '__spec__']

子目录的中的模块没有导入!!!
该例子中的导入等价于
from mypackage import subpackage_1, subpackage_2
因此,导入操作会继续查找 subpackage_1 和 subpackage_2 中的 __init__.py 并执行。(但是此时不会执行 import *)
我们在 subpackage_1 下添加 __init__.py 文件:
__all__ = ['test11', 'test12'] # 默认只导入test11
from mypackage.subpackage_1 import test11
再来导入试试

>>> from mypackage import *
>>> dir()
['__builtins__', '__doc__', '__loader__', '__name__', '__package__', '__spec__', 'subpackage_1', 'subpackage_2']
>>>
>>> dir(subpackage_1)
['__all__', '__builtins__', '__cached__', '__doc__', '__file__', '__loader__', '__name__', '__package__', '__path__', '__spec__', 'test11']

如果想要导入子包的所有模块,则需要更精确指定。
>>> from mypackage.subpackage_1 import *
>>> dir()
['__builtins__', '__doc__', '__loader__', '__name__', '__package__', '__spec__', 'test11', 'test12']
3. 配置模块的初始化操作
在了解了 __init__.py 的工作原理后,应该能理解该文件就是一个正常的python代码文件。
因此可以将初始化代码放入该文件中。
至此。转载请注明出处。

Python __init__.py文件的作用的更多相关文章
- python中__init__.py文件的作用
问题 在执行models.py时,报ImportError:No module named transwarp.db的错误,但明明transwarp下就有db.py文件,路径也没有错误.真是想不通.后 ...
- Python包中 __init__.py文件的作用
原创连接 https://www.cnblogs.com/AlwinXu/p/5598543.html Python包中 __init__.py文件的作用 在创建python包的过程中,IDE都会在包 ...
- Python中__init__.py文件的作用详解
转自http://www.jb51.net/article/92863.htm Python中__init__.py文件的作用详解 http://www.jb51.net/article/86580. ...
- Python学习笔记之__init__.py文件的作用
参考地址:http://www.cnblogs.com/Lands-ljk/p/5880483.html Python __init__.py 作用详解 __init__.py 文件的作用是将文件夹变 ...
- 转载:【学习之家】Python中__init__.py文件的作用
Python中__init__.py文件的作用详解 Python中__init__.py文件的作用详解 来源:学习之家 作者:xuexi110 人气:357 发布时间:2016-09-29 摘要:__ ...
- python包中__init__.py文件的作用
python包中__init__.py文件的作用 __init__.py文件最常用的作用是标识一个文件夹是一个 python包. __init__.py文件的另一个作用是定义模糊导入时要导入的内容. ...
- python2中的__init__.py文件的作用
python2中的__init__.py文件的作用: 1.python的每个模块的包中,都必须有一个__init__.py文件,有了这个文件,我们才能导入这个目录下的module. 2.__init_ ...
- Python __init__.py 文件使用
__init__.py的主要作用是: 1. Python中package的标识,不能删除 2. 定义__all__用来模糊导入 3. 编写Python代码(不建议在__init__中写python模块 ...
- 初学者:__init__.py文件的作用
__init__.py 文件的作用及意义 __init__.py文件是一个包必须的文件,即使它是空的,但也是必须的,如果没有这个文件,python将不会把该文件夹当做一个package,而仅仅是一个d ...
随机推荐
- C++版 - 剑指Offer 面试题45:圆圈中最后剩下的数字(约瑟夫环问题,ZOJ 1088:System Overload类似)题解
剑指Offer 面试题45:圆圈中最后剩下的数字(约瑟夫环问题) 原书题目:0, 1, - , n-1 这n个数字排成一个圈圈,从数字0开始每次从圆圏里删除第m个数字.求出这个圈圈里剩下的最后一个数字 ...
- Chapter 4 Invitations——7
The next day, I was surprised that Jessica wasn't her usual gushing self in Trig and Spanish. 第二天,我很 ...
- JavaScript和Ajax部分(2)
11. DOM如何操作文档的标准节点? 1) 查看节点:使用getElementById(),getElementByName(),getElementByTagName可以查看HTML文档中的任何元 ...
- 开发“todolist“”项目及其自己的感悟
一,项目题目: 实现“todolist项目” 该项目主要可以练习js操控dom事件,事件触发之间的逻辑关系,以及如何写入缓存,获取缓存.固定. 二,todolist简介 ToDoList是一款非常优秀 ...
- vs javascript intellisence失效
前些天写js的时候发现vs的提示都没了...纳闷但是没去了解原因. 今天实在是受不了了. 网上搜了一下,看到msdn文档上一句话,“通过使用 reference 指令,Visual Studio 能够 ...
- shell中$后加引号有什么用($"string"和$'string')
bash&shell系列文章:http://www.cnblogs.com/f-ck-need-u/p/7048359.html 有些时候在某些服务管理脚本中看到$"$string& ...
- python的一些内置模块
整理了几种python的常用内置模块. 内置函数思维导图:https://www.processon.com/view/link/5c7902b1e4b0168e4200846a re模块 re(re ...
- CLR 协变、逆变
看书看得有点晕了,协变.逆变傻傻分不清楚. 看到泛型和委托.委托方法,发现这里面的协变和逆变不一样. 泛型的逆变和协变:如果某个返回类型可以由其基类替换,那么这个类型就是支持协变的.如果某个参数类型可 ...
- [javaEE] Tomcat的安装与配置
下载压缩包,解压缩,好,安装完成 进入解压目录/bin/下面,找到startup.bat,双击,此时如果报错,那么就是没有设置环境变量JAVA_HOME,进入环境变量去设置,JAVA_HOME指向jd ...
- redis实现高并发下的抢购/秒杀功能
之前写过一篇文章,高并发的解决思路(点此进入查看),今天再次抽空整理下实际场景中的具体代码逻辑实现吧:抢购/秒杀是如今很常见的一个应用场景,那么高并发竞争下如何解决超抢(或超卖库存不足为负数的问题)呢 ...