當你去看一些 Python 相關的項目時,常常會看到 __init__.py,當你使用某些編輯器創建 Python Package 的時候,它也會自動給你生成一個 __init__.py 文件。
這玩意有什麼用呢?
我們知道, Python 中的包是可以包含多個 py 模塊的,我們可以在不同的地方通過包名區分使用這些模塊。
話不多說,咱們先來創建一下這樣的目錄:
我們在這裡面創建了三個 Python 子包,裡面都有 __init__ 和 module 的 py 文件。
我們分別在不同包下的 __init__ 中寫一個 print 語句:
接著我們進入 Python ,分別來導入這些模塊:
可以看到,當我們導入父模塊中的子模塊的時候,它會優先執行父模塊中的 init ,接著會執行指定模塊中的 init。
當然,只是導入父模塊的時候只會執行父模塊中的 init:
也就是說,當我們去 import 一個 Package 的時候,它會隱性的去執行 __init__.py , 而在 __init__.py 中定義的對象,會被綁定到當前的命名空間裡面來。
比如有時候我們會這樣去導入一個包下的所有模塊,會這樣操作:
但這個時候你會發現並沒有將相關的子模塊導入進來:
這時候你可能想到了,可以在父模塊中的 __init__.py 做文章,先把它們導入進來不就行了:
這裡的 __all__ 相當於導入 [] 裡面定義的模塊。
這次再導入:
可以看到,所有子模塊就都一併導入進來了。
當然,你也可以在 __init__.py 做一些初始化的操作,比如數據庫 session 的創建:
其實在 Python3.2 版本之前,定義的 Package 下面一定要有 __init__.py 文件,這樣 Python 才知道它是一個 Package,才可以尋找到相關模塊的路徑從而被 import。
而在 Python3.2 之後的版本就不需要再額外的去專門創建一個 __init__.py 來告訴 Python 它是一個 Package 了,因為現在創建的包叫 Namespace package, Python 可以自動搜尋 Package 路徑,哪怕你的父包路徑發生了改變,你在下次導入的時候, Python 還是會自動重新搜索包路徑。
我們把剛剛定義的 __init__ 都給刪掉試試:
接著我們在 Python3.8 版本導入看看:
可以看到,儘管我們在 package 中沒有定義 __init__.py,依然可以導入使用。
以同樣的形式,我們在 Python2 中導入看看:
可以看到,它被整懵逼了...
綜上,__init__.py 會在 import 的時候被執行,而空的 __init__.py 在 Python 新版本中已經不需要你額外去定義了,因為就算你不定義 init, Python 也知道你導入的包路徑,但是如果你想要做一些初始化操作,或者像我們剛剛說的預先導入相關的模塊,那麼定義 __init__.py 還是很有必要的喲。
希望對你有幫助,那麼我們下回見,peace!