Python模塊深入學習
目錄
本文將在學習Python中模塊的概念的基礎上,通過一些示例來繼續學習模塊標準模板、import、from…import 、深入理解模塊、屬性、包等知識。
模塊標準模板
在了解了Python中的模塊知識以後,就來看一下Python中的模塊標準模板。例子中模塊名:。
如下:
解釋如下:
以上就是Python模塊的標準文件模板,當然也可以全部刪掉不寫,但是,按標準辦事肯定沒錯。
後面開始就是真正的代碼部分。
你可能注意到了,使用sys模塊的第一步,就是導入該模塊:
導入sys模塊後,我們就有了變數sys指向該模塊,利用sys這個變數,就可以訪問sys模塊的所有功能。sys模塊有一個argv變數,用list存儲了命令行的所有參數。
import 語句
想使用 Python 源文件,只需在另一個源文件里執行 import 語句,語法如下:
當解釋器遇到 import 語句,如果模塊在當前的搜索路徑就會被導入。
搜索路徑是一個解釋器會先進行搜索的所有目錄的列表。例如:想要導入模塊my_pi,需要把命令放在腳本的頂端。
my_pi.py源碼如下:
在my_module模塊中導入,就可以使用了:
運行結果如下:
一個模塊只會被導入一次,不管你執行了多少次import。這樣可以防止導入模塊被一遍又一遍地執行。
當我們使用import語句的時候,Python解釋器是怎樣找到對應的文件的呢?
這就涉及到Python的搜索路徑,搜索路徑是由一系列目錄名組成的,Python解釋器就依次從這些目錄中去尋找所引入的模塊。這看起來很像環境變數,事實上,也可以通過定義環境變數的方式來確定搜索路徑。
搜索路徑是在Python編譯或安裝的時候確定的,安裝新的庫應該也會修改。
from…import 語句
Python的from語句讓你從模塊中導入一個指定的部分到當前命名空間中,語法如下:
例如:my_pi.py模塊中,添加了兩個函數,、源碼如下:
錯誤示例
在模塊my_module中,這次只導入get_standard_pi函數。導入get_standard_pi,仍調用my_pi.get_pi(),則會報錯NameError,代碼如下:
運行結果:
原因是:由於,這個聲明不會把整個my_pi模塊導入到當前的命名空間中,它只會將my_pi里的get_standard_pi函數引入進來。而實際調用時,調用的,所以提示:,my_pi未定義。
正確示例
在模塊my_module中,這次只導入get_standard_pi()函數。導入get_standard_pi,仍調用my_pi.get_standard_pi(),代碼如下:
運行結果:
From…import* 語句
把一個模塊的所有內容全都導入到當前的命名空間也是可行的,只需使用如下聲明:
這提供了一個簡單的方法來導入一個模塊中的所有項目。然而這種聲明不該被過多地使用,此處也不再舉例。
深入理解模塊
每個模塊有各自獨立的符號表,在模塊內部為所有的函數當作全局符號表來使用。所以,模塊的作者可以放心大膽的在模塊內部使用這些全局變數,而不用擔心把其他用戶的全局變數搞污染。
在一個模塊(或者腳本,或者其他地方)的最前面使用 import 來導入一個模塊,當然這只是一個慣例,而不是強制的。被導入的模塊的名稱將被放入當前操作的模塊的符號表中。
例如:上面例子中的
這樣做並沒有把直接定義在中的函數名稱寫入到當前符號表裡,只是把模塊的名字寫到了那裡。
還有一種導入的方法,可以使用 import 直接把模塊內(函數,變數的)名稱導入到當前操作模塊。比如:
這種導入的方法不會把被導入的模塊的名稱放在當前的字元表中(所以在這個例子裡面,my_pi這個名稱是沒有定義的)。
這還有一種方法,可以一次性的把模塊中的所有(函數,變數)名稱都導入到當前模塊的字元表:
這將把所有的名字都導入進來,但是那些由單一下劃線_開頭的名字不在此例。大多數情況, Python程序員不使用這種方法,因為引入的其它來源的命名,很可能覆蓋了已有的定義。
這也是三種導入方式的重要區別。
屬性
一個模塊被另一個程序第一次引入時,其主程序將運行。如果我們想在模塊被引入時,模塊中的某一程序塊不執行,我們可以用屬性來使該程序塊僅在該模塊自身運行時執行。
基於此,設計如下實例進行驗證:
我們創建2個模塊:、,模塊名分別:、;在模塊中導入模塊。
其中源碼如下:
源碼如下:
運行模塊,運行結果如下:
修改:源碼如下:
運行模塊,運行結果如下:
說明: 每個模塊都有一個屬性,當其值是時,表明該模塊自身在運行,否則是被引入。
包
通過前面的學習,我們已經知道,在解決和其他人的模塊同名時,我們引入了包。此時,模塊的名字就變成了:。
目錄只有包含一個叫做的文件才會被認作是一個包,主要是為了避免一些濫俗的名字(比如叫做 string)不小心的影響搜索路徑中的有效模塊。
最簡單的情況,放一個空的就可以了。當然這個文件中也可以包含一些初始化代碼或者為(將在後面介紹的)變數賦值。
注意當使用這種形式的時候,對應的item既可以是包裡面的子模塊(子包),或者包裡面定義的其他名稱,比如函數,類或者變數。
import語法會首先把item當作一個包定義的名稱,如果沒找到,再試圖按照一個模塊去導入。如果還沒找到,恭喜,一個異常被拋出了。
反之,如果使用形如這種導入形式,除了最後一項,都必須是包,而最後一項則可以是模塊或者是包,但是不可以是類,函數或者變數的名字。
從一個包中導入*
使用形如時,Python會做哪些事情呢?
Python 會進入文件系統,找到這個包裡面所有的子模塊,一個一個的把它們都導入進來。
但是很不幸,這個方法在 Windows平台上工作的就不是非常好,因為Windows是一個大小寫不區分的系統。
在這類平台上,沒有人敢擔保一個叫做 ECHO.py 的文件導入為模塊 echo 還是 Echo 甚至 ECHO。
(例如,Windows 95就很討厭的把每一個文件的首字母大寫顯示)而且 DOS 的 8+3 命名規則對長模塊名稱的處理會把問題搞得更糾結。
為了解決這個問題,只能煩勞包的作者提供一個精確的包的索引了。
導入語句遵循如下規則:
如果包定義文件 存在一個叫做 的列表變數,那麼在使用 的時候就把這個列表中的所有名字作為包內容導入。
作為包的作者,可別忘了在更新包之後保證也更新了啊。你說我就不這麼做,我就不使用導入*這種用法,好吧,沒問題,誰讓你是老闆呢。
例如:我們項目中有一個登陸包,包名:。
如上圖,在中包含如下代碼:
這表示當你使用這種用法時,你只會導入包裡面這三個子模塊。
如果真的沒有定義,那麼使用這種語法的時候,就不會導入包 login 里的任何子模塊。他只是把包company_project.login和它裡面定義的所有內容導入進來(可能運行里定義的初始化代碼)。這會把裡面定義的所有名字導入進來。並且他不會破壞掉我們在這句話之前導入的所有明確指定的模塊。
通常我們並不主張使用這種方法來導入模塊,因為這種方法經常會導致代碼的可讀性降低。不過這樣倒的確是可以省去不少敲鍵的功夫,而且一些模塊都設計成了只能通過特定的方法導入。
記住,使用這種方法永遠不會有錯。事實上,這也是推薦的方法。除非是你要導入的子模塊有可能和其他包的子模塊重名。
如果在結構中包是一個子包(比如這個例子中對於包來說),而你又想導入兄弟包(同級別的包,圖中沒有,假設有個網路請求的network包)你就得使用導入絕對的路徑來導入。
比如,如果模塊 要使用包中的模塊,你就要寫成 。
無論是隱式的還是顯式的相對導入都是從當前模塊開始的。主模塊的名字永遠是,一個Python應用程序的主模塊,應當總是使用絕對路徑引用。
包還提供一個額外的屬性。這是一個目錄列表,裡面每一個包含的目錄都有為這個包服務的,你得在其他被執行前定義哦。可以修改這個變數,用來影響包含在包裡面的模塊和子包。
這個功能並不常用,一般用來擴展包裡面的模塊。
小結
本文在學習Python3中模塊概念的基礎上,通過一些示例來繼續學習了模塊標準模板、import、from…import 、深入理解模塊、屬性、包等知識。
※Python為什麼這麼火,原因竟然是這個……
※Python指南:Python的8個關鍵要素
TAG:Python |