你經常看到卻經常忽視的__init__.py有什么用?


Python 初學者在閱讀一些 Python 開源項目時,常常會看到一個叫做__init__.py的文件。下圖為著名的第三方庫requests的源代碼:

那么__init__.py有什么用呢?本文介紹它的兩個用途。

精簡導入路徑

假設我們有兩個文件main.pywriter.py,他們所在的文件結構如下圖所示:

main.pyDocParser文件夾下面;writer.pyDocParser/microsoft/docx/文件夾下面。writer.py文件中有一個函數write。其內容如下:

現在我想在main.py文件夾調用這個函數,那么我有3種寫法:

1
2
3
from microsoft.word.docx.writer import write
 
write()

運行效果如下圖所示:

或者這樣寫:

1
2
3
from microsoft.word.docx import writer
 
writer.write()

運行效果如下圖所示:

或者這樣寫:

1
2
3
import microsoft.word.docx.writer
 
microsoft.word.docx.writer.write()

運行效果如下圖所示:

但無論那種方法,都要寫長長的路徑,甚為不便。這個時候,我們可以在microsoft文件夾下面創建一個__init__.py文件,並在里面填寫如下內容:

此時,在 main.py,我們導入write函數,就像是從microsoft.py 文件中導入一樣。如下圖所示:

注意上面我說的是就像從microsoft.py 文件中導入一樣,這里是用的文件而不是文件夾

這是因為,當一個文件夾里面有__init__.py以后,這個文件夾就會被 Python 作為一個包(package)來處理。此時,對於這個包里面層級比較深的函數、常量、類,我們可以先把它們導入到__init__.py中。這樣以來,包外面再想導入這些內容時,就可以用from 包名 import 函數名來導入了。

無視工作區的相對引用

為什么會有這個東西呢?這是因為,當有一些代碼會在很多地方被使用時,我們可以把這些代碼打包起來,作為一個公共的部分提供給其他模塊調用。

由於調用包的其他模塊所在的絕對路徑是千變萬化的,所以在包的內部調用自身其他文件中的函數、常量、類,就應該使用相對路徑,而是絕對路徑。

例如,現在我在microsoft文件夾下面再創建一個parse.py文件,它需要導入microsoft/word/docx/writer.py中的write函數,那么代碼可以寫為:

1
2
3
4
5
6
from .word.docx.writer import write
 
 
def parse_doc():
print( '現在在 parse.py 中調用 write 函數')
write()

如下圖所示:

可以看到,此時from .word.docx.writer中的.表示當前包,所以.word.docx.writer表示當前包下面的word 文件夾下面的 docx 文件夾下面的 writer.py 文件。

然后我們修改__init__.py,把parse_doc函數導入進去,如下圖所示:

最后,在main.py中調用這個parse_doc函數,如下圖所示:

可以看到,在包里面的一個文件調用這個包里面的另一個文件,只需要知道另一個文件的相對位置就可以了,不用關心這個包被放在哪里。

並且,上面parse.py中導入write函數的代碼還可以進一步簡化,由於write函數已經被導入到了__init__.py中,所以我們可以直接從.里面導入write函數:

1
from . import write

運行效果如下圖所示:

總結

當一個文件夾里面包含__init__.py時,這個文件夾會被 Python 認為是一個包(package),此時,包內部的文件之間互相導入可以使用相對導入,並且通過提前把函數、常量、類導入到__init__.py中再在其他文件中導入,可以精簡代碼。

 
 
轉自:微信公眾號:未聞Code


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM