淺談Python __init__.py的作用
我們經(jīng)常在python的模塊目錄中會看到 "__init__.py" 這個文件,那么它到底有什么作用呢?
1. 標(biāo)識該目錄是一個python的模塊包(module package)
如果你是使用python的相關(guān)IDE來進(jìn)行開發(fā),那么如果目錄中存在該文件,該目錄就會被識別為 module package 。
2. 簡化模塊導(dǎo)入操作
假設(shè)我們的模塊包的目錄結(jié)構(gòu)如下:
. └── mypackage ├── subpackage_1 │ ├── test11.py │ └── test12.py ├── subpackage_2 │ ├── test21.py │ └── test22.py └── subpackage_3 ├── test31.py └── test32.py
如果我們使用最直接的導(dǎo)入方式,將整個文件拷貝到工程目錄下,然后直接導(dǎo)入:
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
當(dāng)然這個例子里面文件比較少,如果模塊比較大,目錄比較深的話,可能自己都記不清該如何導(dǎo)入。(很有可能,哪怕只想導(dǎo)入一個模塊都要在目錄中找很久)
這種情況下,__init__.py 就很有作用了。我們先來看看該文件是如何工作的。
2.1 __init__.py 是怎么工作的?
實(shí)際上,如果目錄中包含了 __init__.py 時,當(dāng)用 import 導(dǎo)入該目錄時,會執(zhí)行 __init__.py 里面的代碼。
我們在mypackage目錄下增加一個 __init__.py 文件來做一個實(shí)驗(yàn):
. └── 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,如果執(zhí)行了該文件就會輸出:
print("You have imported mypackage")
下面直接用交互模式進(jìn)行 import
>>> import mypackage You have imported mypackage
很顯然,__init__.py 在包被導(dǎo)入時會被執(zhí)行。
2.2 控制模塊導(dǎo)入
我們再做一個實(shí)驗(yàn),在 mypackage/__init__.py 添加以下語句:
from subpackage_1 import test11
我們導(dǎo)入 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'
報錯了。。。怎么回事?
原來,在我們執(zhí)行import時,當(dāng)前目錄是不會變的(就算是執(zhí)行子目錄的文件),還是需要完整的包名。
from mypackage.subpackage_1 import test11
綜上,我們可以在__init__.py 指定默認(rèn)需要導(dǎo)入的模塊
2.3 偷懶的導(dǎo)入方法
有時候我們在做導(dǎo)入時會偷懶,將包中的所有內(nèi)容導(dǎo)入
from mypackage import *
這是怎么實(shí)現(xiàn)的呢? __all__ 變量就是干這個工作的。
__all__ 關(guān)聯(lián)了一個模塊列表,當(dāng)執(zhí)行 from xx import * 時,就會導(dǎo)入列表中的模塊。我們將 __init__.py 修改為 。
__all__ = ['subpackage_1', 'subpackage_2']
這里沒有包含 subpackage_3,是為了證明 __all__ 起作用了,而不是導(dǎo)入了所有子目錄。
>>> from mypackage import * >>> dir() ['__builtins__', '__doc__', '__loader__', '__name__', '__package__', '__spec__', 'subpackage_1', 'subpackage_2'] >>> >>> dir(subpackage_1) ['__doc__', '__loader__', '__name__', '__package__', '__path__', '__spec__']
子目錄的中的模塊沒有導(dǎo)入?。?!
該例子中的導(dǎo)入等價于
from mypackage import subpackage_1, subpackage_2
因此,導(dǎo)入操作會繼續(xù)查找 subpackage_1 和 subpackage_2 中的 __init__.py 并執(zhí)行。(但是此時不會執(zhí)行 import *)
我們在 subpackage_1 下添加 __init__.py 文件:
__all__ = ['test11', 'test12'] # 默認(rèn)只導(dǎo)入test11 from mypackage.subpackage_1 import test11
再來導(dǎo)入試試
>>> 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']
如果想要導(dǎo)入子包的所有模塊,則需要更精確指定。
>>> from mypackage.subpackage_1 import * >>> dir() ['__builtins__', '__doc__', '__loader__', '__name__', '__package__', '__spec__', 'test11', 'test12']
3. 配置模塊的初始化操作
在了解了 __init__.py 的工作原理后,應(yīng)該能理解該文件就是一個正常的python代碼文件。
因此可以將初始化代碼放入該文件中。
到此這篇關(guān)于淺談Python __init__.py的作用的文章就介紹到這了,更多相關(guān)Python __init__.py內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
詳解如何使用pandas進(jìn)行時間序列數(shù)據(jù)的周期轉(zhuǎn)換
時間序列數(shù)據(jù)是數(shù)據(jù)分析中經(jīng)常遇到的類型,為了更多的挖掘出數(shù)據(jù)內(nèi)部的信息,我們常常依據(jù)原始數(shù)據(jù)中的時間周期,將其轉(zhuǎn)換成不同跨度的周期,下面以模擬的K線數(shù)據(jù)為例,演示如何使用pandas來進(jìn)行周期轉(zhuǎn)換,感興趣的朋友可以參考下2024-05-05python將紅底證件照轉(zhuǎn)成藍(lán)底的實(shí)現(xiàn)方法
這篇文章主要介紹了python將紅底證件照轉(zhuǎn)成藍(lán)底,本文給大家分享四種方法通過示例代碼給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下2022-08-08Python算法思想集結(jié)深入理解動態(tài)規(guī)劃
這篇文章主要為大家介紹了Python算法思想集結(jié)深入理解動態(tài)規(guī)劃詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-09-09Python cookbook(數(shù)據(jù)結(jié)構(gòu)與算法)對切片命名清除索引的方法
這篇文章主要介紹了Python cookbook(數(shù)據(jù)結(jié)構(gòu)與算法)對切片命名清除索引的方法,結(jié)合實(shí)例形式分析了Python字符串截取及indices方法映射序列的相關(guān)操作技巧,需要的朋友可以參考下2018-03-03Python OpenCV之圖片縮放的實(shí)現(xiàn)(cv2.resize)
這篇文章主要介紹了Python OpenCV之圖片縮放的實(shí)現(xiàn),文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2019-06-06Python進(jìn)階-函數(shù)默認(rèn)參數(shù)(詳解)
下面小編就為大家?guī)硪黄狿ython進(jìn)階-函數(shù)默認(rèn)參數(shù)(詳解)。小編覺得挺不錯的,現(xiàn)在就分享給大家,也給大家做個參考。一起跟隨小編過來看看吧2017-05-05