標籤:編程 作用 列表 div modules 搜尋 load 完成後 init
一、模組和命名空間
一般來說,Python程式往往由多個模組檔案構成,通過import語句串連在一起。每個模組檔案是一個獨立完備的變數包,即一個命名空間。一個模組檔案不能看到其他檔案定義的變數名,除非它顯示地匯入了那個檔案,所以模組檔案在代碼檔案中起到了最小化命名衝突的作用。因為每個檔案都是一個獨立完備的命名空間,即使在他們拼字相同的情況下,一個檔案的變數名是不會與另一個檔案中的變數衝突的。
注意:import VS from:應該指出,from語句在某種意義上戰勝了模組的名稱空間分割的目的,因為from把變數從一個檔案複製到另一個檔案,這可能導致在匯入的檔案中相同名稱的變數被覆蓋(並且,如果發生這種情況的話,不會為你給出警告)。這根本上會導致名稱空間重疊到一起,至少在複製的變數上會重疊。
二、模組介紹
模組:用來從邏輯上組織Python代碼(變數,函數,類,邏輯:實現一個功能),本質就是.py結尾的Python檔案(檔案名稱:test.py,對應的模組名:test)
包:用來從邏輯上組織模組的,本質就是一個目錄(必須帶有一個__init__.py檔案)
模組分類:
內建模組
自訂模組
第三方模組(需要安裝才能使用)
注意:Python中的模組,在其他語言中叫做類庫。
三、模組匯入和重載
匯入和重載提供了一種自然的程式啟動的選擇,因為匯入操作將會在最後一步執行檔案。
在典型的應用中,匯入者得到了模組檔案中在頂層所定義的所有變數名。這些變數名通常被賦值給通過模組函數、類、變數以及其他被匯出的工具。這些往往都會在其他檔案或程式中使用。表面上來看,一個模組檔案的變數名可以通過兩個Python語句讀取--import和from,以及reload調用。
3.1、模組的顯要特性:屬性
從一般意義上來說,模組往往就是變數名的封裝,被認作是命名空間。在一個包中的變數名就是所謂的屬性:也就是說,屬性就是綁定在特定的對象上的變數名。
舉個例子,使用文字編輯器建立一個名為myfile.py的單行的Python模組檔案,其內容如下:
| 1234 |
# cat myfile.py #!/usr/bin/env python3.5 title = "The Meaning of Life" |
當檔案匯入時,它的代碼運行並產生了模組的屬性。這個指派陳述式建立了一個名為title的模組的屬性。
可以通過兩種不同的方法從其他組件獲得這個模組的title屬性:
第一種,可以通過使用import語句將模組作為一個整體載入,並使用模組名後跟一個屬性名稱來擷取它:
| 123 |
>>> import myfile>>> print(myfile.title) The Meaning of Life |
一般來說,這裡的點號運算式代表了object.attribute的文法,可以從任何的object中取出其任意的屬性,並且這是Python代碼中的一個常用操作。在這裡,我們已經使用了它去擷取在模組myfile中的一個字串變數title,即myfile.titile。
注意:一旦以import方法匯入模組檔案,內建的dir函數可以獲得模組內部的可用的變數名的列表。
第二種,可以通過from語句從模組檔案中獲得(實際上是複製)變數名:(推薦)
| 123 |
>>> from myfile import title>>> print(title) The Meaning of Life |
from和import很相似,只不過增加了對載入組件的變數名的額外的賦值。從技術上講,from複製了模組的屬性,以便屬效能夠成為接收者的直接變數。因此,能夠直接以title(一個變數)引用匯入字串而不是myfile.title(一個屬性引用)。
無論使用的是import還是from去執行匯入操作,模組檔案myfile.py的語句都會執行,並且匯入的組件(對應這裡是互動式提示模式)在頂層檔案中得到了變數名的讀取權。也許在這個簡單的例子中只有一個變數名(變數title被賦值給一個字串),但是如果開始在模組中定義對象,例如,函數和類時,這個概念將會很有用。這樣一些對象就變成了可重要的組件,可以通過變數名被一個或多個用戶端模組讀取。
在實際應用中,模組檔案往往定義了一個以上的可被外部檔案使用的變數名。
注意:import和from列出模組名時,都是使用myfile,沒有.py尾碼。這是因為Python在尋找實際檔案時,依靠Python模組搜尋的路徑定位檔案,找到後自動中加入尾碼名。然而,系統shell命令列中,一定要記得加上尾碼名,但是import語句中則不用。
3.2、匯入模組的所有方法:
| 123456 |
import module_name #表示將模組中的所有代碼載入到這個位置並賦值給變數module_name,並執行模組import libs.module_name #表示從libs目錄下匯入模組檔案module_name,調用方法:libs.module_name.func()import module1_name,module2_name #同時匯入多個模組from module_name import login,logout #相當於將module_name\login中的代碼拿到當前位置執行from module_name import login as module_name_login #對匯入模組中的方法取別名from libs.module_name import func #從目錄下的模組檔案中匯入方法func,調用:func() |
import本質:
匯入模組的本質就是把Python檔案解釋一遍。
匯入包的本質就是執行該包下的__init__.py檔案。
匯入最佳化:
from module_name import login
相比較import module_name,調用時module_name.test(),每次調用時都需要在os.path路徑中檢索導致效率降低,所以使用from...import...匯入,這樣相當於將方法直接拿到調用者中執行。
樣本
3.3、import如何工作
匯入其實是運行時的運算,程式第一次匯入指定檔案時,會執行三個步驟:
a、找到模組檔案
b、編譯成位碼(需要時)
c、執行模組的代碼來建立其所定義的對象
這三個步驟只在程式執行時,模組第一次匯入時才會進行。在這之後,匯入相同模組時,會跳過這三個步驟,而只提取記憶體中已載入的模組對象。python把載入的模組儲存到一個名為sys.modules的表中(list(sys.modules.keys())),並在一次匯入操作的開始檢查該表。如果模組不存在,將會啟動一個三個步驟的過程。
a、搜尋
首先,Python必須尋找到import語句所引用的模組檔案。事實上,路徑和尾碼是刻意省略掉的,因為Python使用了標準模組搜尋路徑來找出import語句所對應的模組檔案。
Python的模組尋找路徑:
| 1234 |
import sys for item in sys.path: print(item) |
Python模組的尋找順序:
| 12345678 |
依次從上往下尋找(上面的優先,且不再搜尋後續路徑),如果都沒有找到,就報錯。D:\oldboy\s14\day5 #執行指令碼所在目錄D:\oldboy\s14 #忽略這個目錄,因為這個目錄是因為pycharm自行添加的C:\Users\chen\AppData\Local\Programs\Python\Python35\python35.zipC:\Users\chen\AppData\Local\Programs\Python\Python35\DLLsC:\Users\chen\AppData\Local\Programs\Python\Python35\libC:\Users\chen\AppData\Local\Programs\Python\Python35C:\Users\chen\AppData\Local\Programs\Python\Python35\lib\site-packages |
注意:sys.path返回的結果是一個列表,當我們需要添加路徑時,只需要向列表中追加即可。
修改Python的模組尋找路徑:
| 12 |
樣本:__file__表示當前檔案sys.path.append(os.path.dirname(os.path.dirname(os.path.abspath(__file__)))) |
模組檔案選擇:
| 1234567891011 |
檔案名稱的尾碼(例如,.py)是刻意從import語句中省略的。Python會選擇在搜尋路徑中第一個符合匯入檔案名稱的檔案。例如,import b形式的import敘述可能會載入。 原始碼檔案b.py位元組碼檔案b.pyc目錄b,包匯入編譯擴充模組(通常用C或C++編寫),匯入時使用動態串連(例如,Linux的b.so以及windows的b.dll)用C編寫的編譯好的內建模組,並通過靜態串連至Python。ZIP檔案組件,匯入時會自動解壓縮。記憶體內映像,對於frozen可執行檔。java類,在jython版本的Python中。.NET組件,在IronPython版本的Python中。 |
b、編譯(可選)
遍曆模組搜尋路徑,找到符合import語句的原始碼檔案後,如果有必要的話,Python接下來會將其編譯成位元組碼。
Python會檢查檔案的時間戳記,如果發現位元組碼檔案比原始碼檔案舊(例如,如果你修改過源檔案),就會在程式運行時自動重建位元組代碼。否則,就會跳過原始碼到位元組碼的編譯步驟。
c、運行
import操作的最後步驟是執行模組的位元組碼。檔案中所有語句會依次執行,從頭到尾,而此步驟中任何對變數名的賦值運算,都會產生所得到的模組檔案的屬性。因此,這個執行步驟會產生模組代碼所定義的所有工具。例如,檔案中的def語句會在匯入時執行,來建立函數,並將模組內的屬性賦值給那些函數。之後,函數就能被程式中這個檔案的匯入者來調用。
3.4、重載
在預設情況下,只是在每次會話的第一次運行。在第一次匯入之後,其他的匯入都不會再工作,甚至在另一個視窗中改變並儲存了模組的原始碼檔案也不行。
| 12345678910 |
$ cat script1.py#!/usr/bin/env python3 print(‘hello world‘) $ python3>>> import script1 # 第一次匯入操作完成後,會執行檔案hello world>>> import script1 # 第二次匯入不會執行>>> |
因為匯入時一個開銷很大的操作,以至於每個檔案、每個程式運行不能夠重複多於一次。匯入必須找到檔案,將其編譯成位元組碼,並且運行代碼。
但是,如果真的想要Python在同一次會話中再次運行檔案(不停止和重新啟動會話),需要調用imp標準庫模組中可用的reload函數。reload函數載入並運行了檔案最新版本的代碼,如果已經在另一個視窗中修改並儲存了它,那將反應出修改變化。
| 12345 |
>>> from imp import reload>>> reload(script1)hello world <module ‘script1‘ from ‘/home/chen/script1.py‘> |
python 小白(無編程基礎,無電腦基礎)的開發之路 輔助知識2 模組