你常常看到的 __init__.py 到底是個啥?

千鋒Python唐小強發表於2020-10-29

當你去看一些 Python 相關的專案時,常常會看到 __init__.py,當你使用某些編輯器建立 Python Package 的時候,它也會自動給你生成一個 __init__.py 檔案。

你常常看到的 __init__.py 到底是個啥?


這玩意有什麼用呢?

我們知道, Python 中的包是可以包含多個 py 模組的,我們可以在不同的地方透過包名區分使用這些模組。


話不多說,我們們先來建立一下這樣的目錄:

你常常看到的 __init__.py 到底是個啥?


我們在這裡面建立了三個 Python 子包,裡面都有 __init__ 和 module 的 py 檔案。

我們分別在不同包下的 __init__ 中寫一個 print 語句:

你常常看到的 __init__.py 到底是個啥?

接著我們進入 Python ,分別來匯入這些模組:

你常常看到的 __init__.py 到底是個啥?

可以看到,當我們匯入父模組中的子模組的時候,它會優先執行父模組中的 init ,接著會執行指定模組中的 init。


當然,只是匯入父模組的時候只會執行父模組中的 init:

你常常看到的 __init__.py 到底是個啥?

也就是說,當我們去 import 一個 Package 的時候,它會隱性的去執行 __init__.py , 而在 __init__.py 中定義的物件,會被繫結到當前的名稱空間裡面來。


比如有時候我們會這樣去匯入一個包下的所有模組,會這樣操作:

你常常看到的 __init__.py 到底是個啥?


但這個時候你會發現並沒有將相關的子模組匯入進來:

你常常看到的 __init__.py 到底是個啥?


這時候你可能想到了,可以在父模組中的 __init__.py 做文章,先把它們匯入進來不就行了:

你常常看到的 __init__.py 到底是個啥?

這裡的 __all__ 相當於匯入 [] 裡面定義的模組。

這次再匯入:

你常常看到的 __init__.py 到底是個啥?

可以看到,所有子模組就都一併匯入進來了。


當然,你也可以在 __init__.py 做一些初始化的操作,比如資料庫 session 的建立:

你常常看到的 __init__.py 到底是個啥?

其實在 Python3.2 版本之前,定義的 Package 下面一定要有 __init__.py 檔案,這樣 Python 才知道它是一個 Package,才可以尋找到相關模組的路徑從而被 import。


而在 Python3.2 之後的版本就不需要再額外的去專門建立一個 __init__.py 來告訴 Python 它是一個 Package 了,因為現在建立的包叫 Namespace package, Python 可以自動搜尋 Package 路徑,哪怕你的父包路徑發生了改變,你在下次匯入的時候, Python 還是會自動重新搜尋包路徑。


我們把剛剛定義的 __init__ 都給刪掉試試:

你常常看到的 __init__.py 到底是個啥?

接著我們在 Python3.8 版本匯入看看:

你常常看到的 __init__.py 到底是個啥?

可以看到,儘管我們在 package 中沒有定義 __init__.py,依然可以匯入使用。


以同樣的形式,我們在 Python2 中匯入看看:

你常常看到的 __init__.py 到底是個啥?

可以看到,它被整懵逼了...


綜上,__init__.py 會在 import 的時候被執行,而空的 __init__.py 在Python 新版本中已經不需要你額外去定義了,因為就算你不定義 init, Python 也知道你匯入的包路徑,但是如果你想要做一些初始化操作,或者像我們剛剛說的預先匯入相關的模組,那麼定義 __init__.py 還是很有必要的喲。


來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/69923331/viewspace-2730780/,如需轉載,請註明出處,否則將追究法律責任。

相關文章