python基础教程:包的创建及导入
包是一種通過用“帶點號的模塊名”來構造?Python 模塊命名空間的方法。 例如,模塊名 A.B 表示 A 包中名為 B 的子模塊。正如模塊的使用使得不同模塊的作者不必擔心彼此的全局變量名稱一樣,使用加點的模塊名可以使得 NumPy 或 Pillow 等多模塊軟件包的作者不必擔心彼此的模塊名稱一樣。
假設你想為聲音文件和聲音數據的統一處理,設計一個模塊集合(一個“包”)。由于存在很多不同的聲音文件格式(通常由它們的擴展名來識別,例如:.wav, .aiff, .au),因此為了不同文件格式間的轉換,你可能需要創建和維護一個不斷增長的模塊集合。 你可能還想對聲音數據還做很多不同的處理(例如,混聲,添加回聲,使用均衡器功能,創造人工立體聲效果), 因此為了實現這些處理,你將另外寫一個無窮盡的模塊流。這是你的包的可能結構(以分層文件系統的形式表示):
__init__.py Initialize the sound packageformats/ Subpackage for file format conversions__init__.pywavread.pywavwrite.pyaiffread.pyaiffwrite.pyauread.pyauwrite.py...effects/ Subpackage for sound effects__init__.pyecho.pysurround.pyreverse.py...filters/ Subpackage for filters__init__.pyequalizer.pyvocoder.pykaraoke.py...?
當導入這個包時,Python搜索 sys.path 里的目錄,查找包的子目錄。
The?init__.py files are required to make Python treat directories containing the file as packages. This prevents directories with a common name, such as string, unintentionally hiding valid modules that occur later on the module search path. In the simplest case, __init__.py can just be an empty file, but it can also execute initialization code for the package or set the __all?variable, described later.
包的用戶可以從包中導入單個模塊,例如:
這會加載子模塊 sound.effects.echo 。但引用它時必須使用它的全名。
導入子模塊的另一種方法是
這也會加載子模塊 echo ,并使其在沒有包前綴的情況下可用,因此可以按如下方式使用:
另一種形式是直接導入所需的函數或變量:
同樣,這也會加載子模塊 echo,但這會使其函數 echofilter() 直接可用:
請注意,當使用 from package import item 時,item可以是包的子模塊(或子包),也可以是包中定義的其他名稱,如函數,類或變量。 import 語句首先測試是否在包中定義了item;如果沒有,它假定它是一個模塊并嘗試加載它。如果找不到它,則引發 ImportError 異常。
相反,當使用 import item.subitem.subsubitem 這樣的語法時,除了最后一項之外的每一項都必須是一個包;最后一項可以是模塊或python包,但不能是前一項中定義的類或函數或變量。
從包中導入
當用戶寫 from sound.effects import * 會發生什么?理想情況下,人們希望這會以某種方式傳遞給文件系統,找到包中存在哪些子模塊,并將它們全部導入。這可能需要很長時間,導入子模塊可能會產生不必要的副作用,這種副作用只有在顯式導入子模塊時才會發生。
唯一的解決方案是讓包作者提供一個包的顯式索引。import 語句使用下面的規范:如果一個包的?init__.py 代碼定義了一個名為 __all?的列表,它會被視為在遇到 from package import?時應該導入的模塊名列表。在發布該包的新版本時,包作者可以決定是否讓此列表保持更新。包作者如果認為從他們的包中導入?的操作沒有必要被使用,也可以決定不支持此列表。例如,文件 sound/effects/__init__.py 可以包含以下代碼:
這意味著 from sound.effects import * 將導入 sound 包的三個命名子模塊。
如果沒有定義 __all__,from sound.effects import * 語句 不 會從包 sound.effects 中導入所有子模塊到當前命名空間;它只確保導入了包 sound.effects (可能運行任何在 __init__.py 中的初始化代碼),然后導入包中定義的任何名稱。這包括 __init__.py` 定義的任何名稱(以及顯式加載的子模塊)。它還包括由之前的 import 語句顯式加載的包的任何子模塊。思考下面的代碼:
import sound.effects.surround from sound.effects import *?
在這個例子中, echo 和 surround 模塊是在執行 from...import 語句時導入到當前命名空間中的,因為它們定義在 sound.effects 包中。(這在定義了?all?時也有效。)
雖然某些模塊被設計為在使用 import * 時只導出遵循某些模式的名稱,但在生產代碼中它仍然被認為是不好的做法。
請記住,使用 from Package import specific_submodule 沒有任何問題!實際上,除非導入模塊需要使用來自不同包的同名子模塊,否則這是推薦的表示法。
子包參考
當包被構造成子包時(與示例中的 sound 包一樣),你可以使用絕對導入來引用兄弟包的子模塊。例如,如果模塊 sound.filters.vocoder 需要在 sound.effects 包中使用 echo 模塊,它可以使用 from sound.effects import echo 。
你還可以使用import語句的 from module import name 形式編寫相對導入。這些導入使用前導點來指示相對導入中涉及的當前包和父包。例如,從 surround 模塊,你可以使用:
from .. import formats from ..filters import equalizer?
請注意,相對導入是基于當前模塊的名稱進行導入的。由于主模塊的名稱總是 "__main__" ,因此用作Python應用程序主模塊的模塊必須始終使用絕對導入。
多個目錄中的包
包支持另一個特殊屬性,?path?。它被初始化為一個列表,其中包含在執行該文件中的代碼之前保存包的文件 __init__.py 的目錄的名稱。這個變量可以修改;這樣做會影響將來對包中包含的模塊和子包的搜索。
雖然通常不需要此功能,但它可用于擴展程序包中的模塊集。
腳注
[1] 實際上,函數定義也是“被執行”的“語句”;模塊級函數定義的執行在模塊的全局符號表中輸入該函數名。
轉載于:https://www.cnblogs.com/yuanrenxue/p/10723272.html
總結
以上是生活随笔為你收集整理的python基础教程:包的创建及导入的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Arm汇编指令集1
- 下一篇: dos模式下切换电脑用户