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

當你去看一些 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 還是很有必要的喲。


希望對你有幫助,那麼我們下回見,peace!


分享到:


相關文章: