Python 包
包 定義
為了組織好模塊,會將多個模塊分為包。Python 處理包也是相當方便的。簡單來說,包就是文件夾,但該文件夾下必須存在 __init__.py 文件。
常見的包結構如下:
最簡單的情況下,只需要一個空的 __init__.py 文件即可。當然它也可以執行包的初始化代碼,或者定義稍后介紹的 __all__ 變量。當然包底下也能包含包,這和文件夾一樣,還是比較好理解的。
導入包
包的導入仍使用 import 、 from ... import 語句,使用 “圓點模塊名” 的結構化模塊命名空間。 下面來看一個包的例子來了解下具體的運作。(官方文檔中的例子)
假設你現在想要設計一個模塊集(一個“包”)來統一處理聲音文件和聲音數據。存在幾種不同的聲音格式(通常由它們的擴展名來標識,例如: .wav, .aiff, .au )於是,為了在不同類型的文件格式之間轉換,你需要維護一個不斷增長的包集合。可能你還想要對聲音數據做很多不同的操作(例如混音,添加回聲,應用平衡 功能,創建一個人造效果)所以你要加入一個無限流模塊來執行這些操作。你的包可能會是這個樣子(通過分級的文件體系來進行分組):
用戶可以每次只導入包里的特定模塊,例如: import sound.efforts.echo 這樣就導入了 sound.effects.echo 子模塊。它必須通過完整的名稱來引用:
sound.effects.echo.echofilter(input, output, delay=0.7, atten=4)
導入包時有一個可以選擇的方式: from sound.effects import echo 這樣就加載了 echo 子模塊,並且使得它在沒有包前綴的情況下也可以使用,所以它可以如下方式調用:
echo.echofilter(input, output, delay=0.7, atten=4)
還有另一種變體用於直接導入函數或變量: from sound.effects.echo import echofilter 這樣就又一次加載了 echo 字模塊,但這樣就可以直接調用它的 echofilter() 函數:
echo.echofilter(input, output, delay=0.7, atten=4)
需要注意的是 from package import item 方式導入包時,這個子項(item)既可以是子包也可以是其他命名,如函數、類、變量等。若無,會引發ImportError異常。
而用類似 import item.subitem.subsubitem 這樣的語法時,這些子項必須是包,最后的子項可以是包或模塊,但不能是類、函數、變量等。
從 * 導入包
import * 這樣的語句理論上是希望文件系統找出包中所有的子模塊,然后導入它們。這可能會花長時間,並出現邊界效應等。Python 解決方案是提供一個明確的包索引。
這個索引由 __init__.py 定義 __all__ 變量,該變量為一列表,如上例 sound/effects 下的 __init__.py 中,可定義 __all__ = ["echo","surround","reverse"]
這意味着, from sound.effects import * 會從對應的包中導入以上三個子模塊; 盡管提供 import * 的方法,仍不建議在生產代碼中使用這種寫法。
包內引用
如果是子包內的引用,可以按相對位置引入子模塊 以 echo 模塊為例,可以引用如下:
1 from . import reverse # 同級目錄 導入 reverse 2 from .. import frormats # 上級目錄 導入 frormats 3 from ..filters import equalizer # 上級目錄的filters模塊下 導入 equalizer
多重目錄包搜索
包支持一個更為特殊的特性, __path__ 在包的 __init__.py 文件代碼執行前,該變量初始化一個目錄名列表。作用於子包和模塊的搜索功能。
該功能可以用於擴展包中的模塊集,不過不常用。