Python中 __init__.py的作用
我們經(jīng)常在python的模塊目錄中會看到 __init__.py 這個文件,那么它到底有什么作用呢?
1.標識該目錄是一個python的模塊包(module package)
如果你是使用python的相關(guān)IDE來進行開發(fā),那么如果目錄中存在該文件,該目錄就會被識別為 module package。
2. 簡化模塊導入操作
假設(shè)我們的模塊包的目錄結(jié)構(gòu)如下:
. └── 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 導入該目錄時,會執(zhí)行__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.pymypackage/__init__.py里面加一個print,如果執(zhí)行了該文件就會輸出:
print("You have imported mypackage")下面直接用交互模式進行 import
>>> import mypackage You have imported mypackage很顯然,init.py 在包被導入時會被執(zhí)行。
2.2 控制模塊導入
我們再做一個實驗,在 mypackage/__init__.py添加以下語句:
from subpackage_1 import test11我們導入 mypackage 試試:
''' 遇到問題沒人解答?小編創(chuàng)建了一個Python學習交流QQ群:778463939 尋找有志同道合的小伙伴,互幫互助,群里還有不錯的視頻學習教程和PDF電子書! ''' >>> 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'報錯了。。。怎么回事?
原來,在我們執(zhí)行import時,當前目錄是不會變的(就算是執(zhí)行子目錄的文件),還是需要完整的包名。
from mypackage.subpackage_1 import test11綜上,我們可以在__init__.py 指定默認需要導入的模塊
2.3 偷懶的導入方法
有時候我們在做導入時會偷懶,將包中的所有內(nèi)容導入
from mypackage import *這是怎么實現(xiàn)的呢?__all__變量就是干這個工作的。
__all__關(guān)聯(lián)了一個模塊列表,當執(zhí)行from xx import *時,就會導入列表中的模塊。我們將 init.py 修改為 。
__all__ = ['subpackage_1', 'subpackage_2']這里沒有包含 subpackage_3,是為了證明 __all__起作用了,而不是導入了所有子目錄。
''' 遇到問題沒人解答?小編創(chuàng)建了一個Python學習交流QQ群:778463939 尋找有志同道合的小伙伴,互幫互助,群里還有不錯的視頻學習教程和PDF電子書! ''' >>> 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因此,導入操作會繼續(xù)查找 subpackage_1 和 subpackage_2 中的 __init__.py 并執(zhí)行。(但是此時不會執(zhí)行import *)
我們在 subpackage_1 下添加 init.py 文件:
__all__ = ['test11', 'test12']# 默認只導入test11 from mypackage.subpackage_1 import test11再來導入試試
''' 遇到問題沒人解答?小編創(chuàng)建了一個Python學習交流QQ群:778463939 尋找有志同道合的小伙伴,互幫互助,群里還有不錯的視頻學習教程和PDF電子書! ''' >>> 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 的工作原理后,應(yīng)該能理解該文件就是一個正常的python代碼文件。
因此可以將初始化代碼放入該文件中。
總結(jié)
以上是生活随笔為你收集整理的Python中 __init__.py的作用的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 19道Python练习题
- 下一篇: Python那些优雅的写法:switch