Python雜談: __init__.py的作用

來源:互聯網
上載者:User

標籤:bsp   pytho   指定   添加   如何   互動模式   代碼   匯入   str   

  我們經常在python的模組目錄中會看到 "__init__.py"  這個檔案,那麼它到底有什麼作用呢?

 

1. 標識該目錄是一個python的模組包(module package)

  如果你是使用python的相關IDE來進行開發,那麼如果目錄中存在該檔案,該目錄就會被識別為 module package 。

2. 簡化模組匯入操作

  假設我們的模組包的目錄結構如下:

.└── mypackage    ├── subpackage_1    │   ├── test11.py    │   └── test12.py    ├── subpackage_2    │   ├── test21.py    │   └── test22.py    └── subpackage_3        ├── test31.py        └── test32.py

   

  如果我們使用最直接的匯入方式,將整個檔案拷貝到工程目錄下,然後直接匯入:

from mypackage.subpackage_1 import test11from mypackage.subpackage_1 import test12from mypackage.subpackage_2 import test21from mypackage.subpackage_2 import test22from mypackage.subpackage_3 import test31from mypackage.subpackage_3 import test32

  當然這個例子裡面檔案比較少,如果模組比較大,目錄比較深的話,可能自己都記不清該如何匯入。(很有可能,哪怕只想匯入一個模組都要在目錄中找很久)

  這種情況下,__init__.py 就很有作用了。我們先來看看該檔案是如何工作的。

2.1 __init__.py 是怎麼工作的?

  實際上,如果目錄中包含了 __init__.py 時,當用 import 匯入該目錄時,實際上會執行 __init__.py 裡面的代碼。

  我們在mypackage目錄下增加一個 __init__.py 檔案來做一個實驗:

.└── 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,如果執行了該檔案就會輸出:

print("You have imported mypackage")

  下面直接用互動模式進行 import

>>> import mypackageYou have imported mypackage

  很顯然,__init__.py 在包被匯入時會被執行。

2.2  控制模組匯入

  我們再做一個實驗,在 mypackage/__init__.py 添加以下語句:

from subpackage_1 import test11

  我們匯入 mypackage 試試:

>>> import mypackageTraceback (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 test11ImportError: No module named ‘subpackage_1‘

  報錯了。。。怎麼回事?

  原來,在我們執行import時,目前的目錄是不會變的(就算是執行子目錄的檔案),還是需要完整的包名。

from mypackage.subpackage_1 import test11

  綜上,我們可以在__init__.py 指定預設需要匯入的模組  

2.3  偷懶的匯入方法

  有時候我們在做匯入時會偷懶,將包中的所有內容匯入

from mypackage import *

  這是怎麼實現的呢? __all__ 變數就是幹這個工作的。

  __all__ 關聯了一個模組列表,當執行 from xx import * 時,就會匯入列表中的模組。我們將 __init__.py 修改為 。

__all__ = [‘subpackage_1‘, ‘subpackage_2‘]

  這裡沒有包含 subpackage_3,是為了證明 __all__ 起作用了,而不是匯入了所有子目錄。

>>> from mypackage import *>>> dir()[‘__builtins__‘, ‘__doc__‘, ‘__loader__‘, ‘__name__‘, ‘__package__‘, ‘__spec__‘, ‘subpackage_1‘, ‘subpackage_2‘]>>> >>> dir(subpackage_1)[‘__doc__‘, ‘__loader__‘, ‘__name__‘, ‘__package__‘, ‘__path__‘, ‘__spec__‘]

  子目錄的中的模組沒有匯入!!!

  該例子中的匯入等價於

from mypackage import subpackage_1, subpackage_2

  因此,匯入操作會繼續尋找 subpackage_1 和 subpackage_2 中的 __init__.py 並執行。(但是此時不會執行 import *

  我們在 subpackage_1 下添加 __init__.py 檔案:

__all__ = [‘test11‘, ‘test12‘]# 預設只匯入test11from mypackage.subpackage_1 import test11

  再來匯入試試

>>> 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‘]

  如果想要匯入子包的所有模組,則需要更精確指定。

>>> from mypackage.subpackage_1 import *>>> dir()[‘__builtins__‘, ‘__doc__‘, ‘__loader__‘, ‘__name__‘, ‘__package__‘, ‘__spec__‘, ‘test11‘, ‘test12‘]
3. 配置模組的初始化操作

  在瞭解了 __init__.py 的工作原理後,應該能理解該檔案就是一個正常的python代碼檔案。

  因此可以將初始化代碼放入該檔案中。

  

 

 

  

 

  

Python雜談: __init__.py的作用

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.