一剩辟、模塊
1元扔、模塊和導(dǎo)入
當(dāng)程序代碼量變得相當(dāng)大躯保、邏輯結(jié)構(gòu)變得非常復(fù)雜的時(shí)候,我們最好把代碼按照邏輯和功能劃分成一些有組織的代碼塊澎语,并將其保存到一個(gè)個(gè)獨(dú)立的文件當(dāng)中途事。這些文件可以包含可執(zhí)行代碼、函數(shù)擅羞、類或者這些東西的組合尸变,這些自我包含并且有組織的代碼塊就是模塊( module )。模塊是最高級(jí)別的 Python 代碼組織單元减俏。
模塊往往對(duì)應(yīng)于物理機(jī)上的 Python 文件(或者是用外部語(yǔ)言如C召烂、Java或C#編寫而成的擴(kuò)展)。當(dāng)你創(chuàng)建了一個(gè) Python 源文件娃承,其對(duì)應(yīng)的模塊的名字就是不帶 .py 后綴的文件名奏夫。一個(gè)模塊(Python程序文件)創(chuàng)建之后, 你可以從另一個(gè)文件中使用 import 語(yǔ)句導(dǎo)入這個(gè)模塊來(lái)使用草慧,從而實(shí)現(xiàn)代碼的重用桶蛔。這個(gè)把其他模塊附加到你的代碼中的操作叫做導(dǎo)入( import )。導(dǎo)入其他模塊之后就可以使用導(dǎo)入的模塊中定義的變量名漫谷。
2仔雷、模塊的作用
代碼重用
因?yàn)槟K對(duì)應(yīng)于 Python 文件,所以模塊中的代碼可以永久保存舔示。你可以按照需要在代碼中任意次數(shù)的使用導(dǎo)入的模塊中定義的變量名(函數(shù)碟婆、類等),甚至可以重新導(dǎo)入模塊惕稻。除了作為最高級(jí)別的 Python 代碼組織單元竖共,模塊(以及 模塊包)也是 Python 中程序代碼重用的最高層次。
系統(tǒng)命名空間的劃分
模塊還是定義變量名的空間俺祠,其內(nèi)部定義的變量名作為模塊的屬性公给,可以通過(guò)導(dǎo)入被多個(gè)外部的文件中的代碼引用借帘。
模塊將變量名封裝進(jìn)了自己的命名空間,這一點(diǎn)對(duì)避免變量名的沖突很有幫助淌铐。所有的一切都存在于 ”模塊“ 中肺然,可執(zhí)行的代碼以及創(chuàng)建的對(duì)象都毫無(wú)疑問(wèn)的封裝在模塊之中。正式由于這一點(diǎn)腿准,模塊是組織系統(tǒng)組件的天然工具际起。
實(shí)現(xiàn)共享服務(wù)和數(shù)據(jù)
從操作的角度來(lái)看,模塊對(duì)實(shí)現(xiàn)跨系統(tǒng)共享的組件是很方便的吐葱,只需要在不同的文件中導(dǎo)入相同的模塊即可街望。
3、Python 的程序架構(gòu)
一個(gè) Python 程序通常都不僅僅涉及一個(gè)文件弟跑,一般都會(huì)采用多文件系統(tǒng)的形式灾前。即使編寫單個(gè)文件,幾乎也一定會(huì)導(dǎo)入標(biāo)準(zhǔn)庫(kù)模塊或者使用到其他人已經(jīng)寫好的外部文件窖认。
一般來(lái)講一個(gè)完整的程序由啟動(dòng)運(yùn)行的腳本文件以及零個(gè)或多個(gè)作為支持(用作導(dǎo)入)的文件組成豫柬。在 Python 中告希,頂層文件包含了程序的主要的控制流程:這就是你需要運(yùn)行來(lái)啟動(dòng)程序的文件扑浸。作為模塊被導(dǎo)入的文件通常在運(yùn)行時(shí)不需要直接做任何事,它提供了頂層文件運(yùn)行所需要的各種組件(普通變量燕偶、函數(shù)喝噪、類等)。頂層文件使用了在模塊文件中定義的組件指么,而這些模塊使用了其他模塊所定義的組件酝惧。
在 Python 中,一個(gè)文件導(dǎo)入了一個(gè)模塊來(lái)獲得這個(gè)模塊中定義的變量的訪問(wèn)權(quán)伯诬,這些變量被認(rèn)作是這個(gè)模塊的屬性晚唇。導(dǎo)入的概念在 Python 之中貫穿始末。任何文件都能從任何其他文件中導(dǎo)入其變量盗似,導(dǎo)入鏈要多深就有多深哩陕。
4、標(biāo)準(zhǔn)庫(kù)模塊
Python 自帶了很多實(shí)用的模塊赫舒,稱為標(biāo)準(zhǔn)鏈接庫(kù)悍及。這個(gè)集合體大約有200多個(gè)模塊,包含與平臺(tái)不相關(guān)(不依賴于具體的系統(tǒng)接癌,可以在任何系統(tǒng)上以同樣的方式調(diào)用心赶,也就是說(shuō)這些標(biāo)準(zhǔn)庫(kù)模塊是跨平臺(tái)的)的常見(jiàn)程序設(shè)計(jì)任務(wù):操作系統(tǒng)接口、對(duì)象永久保存缺猛、文字模式匹配缨叫、網(wǎng)絡(luò)和 internet 腳本椭符、GUI 建構(gòu)等。
這些工具都不是 Python 語(yǔ)言的組成部分耻姥,但是艰山,你可以在任何安裝了 Python 的環(huán)境中,導(dǎo)入適當(dāng)?shù)哪K來(lái)使用咏闪。因?yàn)檫@些都是標(biāo)準(zhǔn)庫(kù)模曙搬,所以他們一定可以用,而且在執(zhí)行 Python 的絕大數(shù)平臺(tái)上都可以運(yùn)行鸽嫂。
二纵装、模塊的導(dǎo)入
模塊中的代碼會(huì)在首次導(dǎo)入時(shí)執(zhí)行,首先建立空的模塊對(duì)象据某,然后按照從頭到尾的順序橡娄,逐一執(zhí)行該模塊內(nèi)的語(yǔ)句。頂層(不在def或class之內(nèi))的賦值語(yǔ)句(例如癣籽,=挽唉、def 和 class等)生成的變量會(huì)成為模塊對(duì)象的屬性,這些變量名會(huì)存儲(chǔ)在模塊的命名空間內(nèi)筷狼。模塊的命名空間能通過(guò)屬性 __dict__ 或內(nèi)建函數(shù) dir() 獲取瓶籽。
1、模塊文件的命名
任何以 “.py” 為后綴名的 Python 文件都會(huì)被自動(dòng)認(rèn)為是 Python 模塊埂材,一般來(lái)說(shuō)塑顺,Python 文件怎么命名都可以,但是如果打算將其作為模塊導(dǎo)入俏险,文件必須以 ”.py“ 結(jié)尾严拒。
對(duì)于會(huì)執(zhí)行但不會(huì)被導(dǎo)入的頂層文件而言,.py 后綴從技術(shù)上來(lái)說(shuō)是可有可無(wú)的竖独,但是每次都加上去裤唠,可以確保文件類型更醒目,并使其以后可以被導(dǎo)入到任何文件中莹痢。
因?yàn)槟K名在 Python 程序中會(huì)變成變量名(沒(méi)有.py)种蘸。因此Python文件應(yīng)該遵循普通變量名的命名規(guī)則。事實(shí)上格二,包導(dǎo)入中所用的模塊的文件名和目錄名都必須遵循變量名規(guī)則劈彪。
2、導(dǎo)入模塊的步驟
在Python中顶猜,導(dǎo)入并不是把一個(gè)文件文本插入另一個(gè)文件中沧奴。導(dǎo)入其實(shí)是運(yùn)行時(shí)的運(yùn)算,程序第一次導(dǎo)入指定文件時(shí)长窄,會(huì)執(zhí)行三個(gè)步驟滔吠。
1纲菌、搜索找到模塊文件。
2疮绷、編譯成字節(jié)碼(需要時(shí))翰舌。
3、執(zhí)行模塊的代碼來(lái)創(chuàng)建其所定義的對(duì)象冬骚,定義 import 語(yǔ)句所在文件的作用域的局部命名空間中的一個(gè)或多個(gè)變量名椅贱。
這三個(gè)步驟只在模塊第一次導(dǎo)入時(shí)才會(huì)執(zhí)行。在這之后只冻,導(dǎo)入相同模塊時(shí)庇麦,會(huì)跳過(guò)這三個(gè)步驟,而只是提取內(nèi)存中已加載的模塊對(duì)象喜德。這是有意而為之的山橄,因?yàn)樵摬僮鏖_銷較大。如果你在模塊已加載后還需要再次導(dǎo)入(例如舍悯,為了支持終端用戶的定制)航棱,你就得通過(guò)調(diào)用 reload() 強(qiáng)制導(dǎo)入模塊。
從技術(shù)上講萌衬,Python 把載入的模塊存儲(chǔ)到一個(gè)名為 sys.modules 的表中饮醇,并在導(dǎo)入操作的開始檢查該表。如果模塊不存在奄薇,將會(huì)自動(dòng)執(zhí)行上面的三個(gè)步驟驳阎。
搜索
Python 會(huì)遍歷模塊搜索路徑抗愁,查找 import 語(yǔ)句所引用的模塊文件馁蒂。在導(dǎo)入者文件中,只能列出要導(dǎo)入的模塊文件的簡(jiǎn)單名稱蜘腌,路徑和后綴是刻意省略掉的沫屡。
當(dāng)一個(gè)模塊被導(dǎo)入時(shí),Python 會(huì)把程序內(nèi)部的模塊名映射到外部物理環(huán)境中的文件名撮珠,也就是將模塊搜索路徑中的目錄路徑添加在模塊名前邊沮脖,并在模塊名的后邊添加 .py 或其他后綴名。
編譯
找到模塊文件后芯急,Python 會(huì)查找對(duì)應(yīng)的 .pyc 字節(jié)碼文件勺届。如果沒(méi)有字節(jié)碼文件,Python 會(huì)將模塊文件編譯成字節(jié)碼文件娶耍。如果找到對(duì)應(yīng)的字節(jié)碼文件免姿,Python 會(huì)檢查文件的時(shí)間戳,如果發(fā)現(xiàn)字節(jié)碼文件比模塊文件舊(例如榕酒,如果你修改過(guò)源文件)胚膊,就會(huì)重新編譯模塊文件生成新的字節(jié)碼文件故俐。如果字節(jié)碼文件不比對(duì)應(yīng)的 .py 源代碼文件舊,就會(huì)跳過(guò)源代碼到字節(jié)碼的編譯步驟紊婉。
如果 Python 在搜索路徑上只發(fā)現(xiàn)了字節(jié)碼文件药版,而沒(méi)有源代碼,就會(huì)直接加載字節(jié)碼文件(這意味著你可以把一個(gè)程序只作為字節(jié)碼文件發(fā)布喻犁,而避免發(fā)送源代碼)槽片。換句話說(shuō),直接使用字節(jié)碼文件跳過(guò)編譯步驟肢础,會(huì)提高程序的啟動(dòng)提速筐乳。
通常不會(huì)看見(jiàn)程序頂層文件的 .pyc 字節(jié)碼文件,除非這個(gè)文件也別其他文件導(dǎo)入:只有被導(dǎo)入的文件才會(huì)在機(jī)器上留下 .pyc 乔妈。頂層文件的字節(jié)碼是在內(nèi)部使用后就丟棄了蝙云,被導(dǎo)入文件的字節(jié)碼則保存在文件中從而可以提高之后導(dǎo)入的速度。
頂層文件通常是設(shè)計(jì)成直接執(zhí)行路召,而不是被導(dǎo)入的勃刨。
運(yùn)行
import 操作的最后步驟是執(zhí)行模塊的字節(jié)碼。文件中所有語(yǔ)句會(huì)從頭到尾依次執(zhí)行股淡,而此步驟中任何對(duì)變量名的賦值運(yùn)算身隐,都會(huì)產(chǎn)生模塊文件的屬性。因此唯灵,這個(gè)執(zhí)行步驟會(huì)生成模塊代碼所定義的所有工具贾铝。
因?yàn)樽詈蟮膶?dǎo)入步驟實(shí)際上是執(zhí)行文件的程序代碼,如果模塊文件中任何頂層代碼確實(shí)做什么實(shí)際的工作垢揩,你就會(huì)在導(dǎo)入時(shí)看見(jiàn)其結(jié)果。
3叁巨、import 語(yǔ)句
常見(jiàn)的 import 導(dǎo)入語(yǔ)句可以分為兩種:?jiǎn)为?dú)的 import 語(yǔ)句用來(lái)導(dǎo)入模塊名;帶有
from 的 import 語(yǔ)句用來(lái)導(dǎo)入模塊中的變量名锋勺,同時(shí)可以使用 *
號(hào)導(dǎo)入模塊中的所有變量。在以上兩種語(yǔ)句中狡蝶,我們都可以使用 as 語(yǔ)句為導(dǎo)入的模塊或變量指定別名庶橱。當(dāng)語(yǔ)句包含多個(gè)子句(以逗號(hào)分隔)時(shí)贪惹,為每個(gè)子句分別執(zhí)行模塊導(dǎo)入的三個(gè)步驟,就像子句已被分隔為單獨(dú)的 import 語(yǔ)句一樣馍乙。
如果導(dǎo)入的模塊被成功檢索到布近,它將通過(guò)以下三種方式之一綁定到本地命名空間:
- 如果模塊名后面是 as垫释,則 as 之后的變量名將在本地命名空間中綁定為對(duì)導(dǎo)入的模塊對(duì)象的引用。
- 如果未指定其他名稱棵譬,并且正在導(dǎo)入的模塊是頂級(jí)模塊(),則模塊的名稱將在本地命名空間中綁定為對(duì)導(dǎo)入模塊對(duì)象的引用订咸。
- 如果正在導(dǎo)入的模塊不是頂級(jí)模塊,則包含該模塊的頂級(jí)包的名稱在本地命名空間中被綁定為對(duì)頂級(jí)包的引用脏嚷。導(dǎo)入的模塊必須使用其完全限定名稱而不能直接訪問(wèn)瞒御。包的概念會(huì)在后續(xù)章節(jié)介紹父叙。
from 形式會(huì)多一些復(fù)雜的過(guò)程:
- 找到 from 子句中指定的模塊肴裙,如果需要趾唱,加載和初始化它蜻懦;
- 對(duì)于 import 子句中指定的每個(gè)標(biāo)識(shí)符:
a. 檢查導(dǎo)入的模塊是否具有該名稱的屬性;
b. 如果沒(méi)有宛乃,請(qǐng)嘗試導(dǎo)入具有該名稱的子模塊,然后再次檢查導(dǎo)入的模塊的該屬性征炼;
c. 如果未找到該屬性,則引發(fā) ImportError柒室;
d. 如果找到該名稱的屬性,對(duì)該屬性的引用存儲(chǔ)在本地命名空間中雄右,使用 as 子句中的名稱(如果存在)纺讲,否則使用屬性名稱;
如果在 from 語(yǔ)句中 import 后面的標(biāo)識(shí)符列表被替換為星號(hào)(*)熬甚,則模塊中定義的所有公共名稱都在 import 語(yǔ)句所在的作用域的本地命名空間中綁定。
(1)import 形式
import 語(yǔ)句將模塊導(dǎo)入文件中:
import module_name
import 是可執(zhí)行語(yǔ)句乡括,就像 def 一樣智厌,它是隱性的賦值語(yǔ)句盲赊。當(dāng) Python 執(zhí)行到這個(gè)語(yǔ)句時(shí)铣鹏,會(huì)將導(dǎo)入生成的模塊對(duì)象賦值給 import 語(yǔ)句后面的模塊名哀蘑,而模塊文件頂層對(duì)任意類型賦值了的變量名,都會(huì)產(chǎn)生為模塊對(duì)象的屬性绘迁。
一旦導(dǎo)入完成合溺,一個(gè)模塊的屬性(函數(shù)和變量)可以通過(guò)熟悉的 (. )句點(diǎn)屬性標(biāo)識(shí)法訪問(wèn)缀台。
module.function()
module.variable
import 語(yǔ)句組合兩個(gè)操作;它搜索指定的模塊并根據(jù)需要執(zhí)行模塊以得到模塊對(duì)象膛腐,然后將模塊對(duì)象綁定到本地作用域中的模塊名恭朗。
import 語(yǔ)句的搜索操作被定義為:使用適當(dāng)?shù)膮?shù)調(diào)用 __import__() 函數(shù)。直接調(diào)用 __import__() 只執(zhí)行模塊搜索依疼,如果找到痰腮,則執(zhí)行模塊創(chuàng)建操作,并返回模塊對(duì)象律罢。如果找不到指定的模塊膀值,則會(huì)引發(fā) ImportError。雖然可能會(huì)伴隨著某些其他的操作误辑,例如導(dǎo)入父包以及更新各種緩存(包括sys.modules)沧踏,但只有 import 語(yǔ)句會(huì)執(zhí)行名稱綁定操作。
屬性名的點(diǎn)號(hào)運(yùn)算
在 Python 之中巾钉,可以使用點(diǎn)號(hào)運(yùn)算語(yǔ)法 object.attribute 獲取任意的 object 的attribute 屬性翘狱。
點(diǎn)號(hào)運(yùn)算符其實(shí)就是表達(dá)式,傳回和對(duì)象相配的屬性名的值砰苍。當(dāng)使用點(diǎn)號(hào)運(yùn)算符來(lái)讀取變量名時(shí),就把明確的對(duì)象提供給 Python 赚导, LEGB 規(guī)則只適用于無(wú)點(diǎn)號(hào)運(yùn)算的純變量名。
簡(jiǎn)單變量名
X 是指在當(dāng)前作用域內(nèi)搜索變量名 X(遵循LEGB規(guī)則)
點(diǎn)號(hào)運(yùn)算
X吼旧,Y 是指在當(dāng)前范圍內(nèi)搜索 X,然后搜索對(duì)象 X 之中的屬性 Y(而非在作用域里)掂为。
多層點(diǎn)號(hào)運(yùn)算
X,Y勇哗,Z 指的是在當(dāng)前范圍內(nèi)搜索 X,然后搜索對(duì)象 X 之中的屬性 Y野揪,然后在對(duì)象X.Y 中搜索屬性 Z 。
通用性
點(diǎn)號(hào)運(yùn)算可用于任何具有屬性的對(duì)象:模塊斯稳、類迹恐、C 擴(kuò)展類型等。
(2)from - import 形式
使用 from-import 語(yǔ)句可以將模塊的屬性導(dǎo)入到當(dāng)前作用域殴边,并綁定到指定的變量名。
from module import name1[, name2[,... nameN]]
from 的第一步驟也是普通的導(dǎo)入操作蜕青。因此捧韵,from 總是會(huì)把整個(gè)模塊導(dǎo)入到內(nèi)存中(如果還沒(méi)被導(dǎo)入的話),無(wú)論是從這個(gè)文件中復(fù)制出多少變量名再来。只加載模塊文件的一部分(例如,一個(gè)函數(shù))是不可能的搜变。但是因?yàn)槟K在 Python 之中是字節(jié)碼而不是機(jī)器碼针炉,通衬铀可以忽略效率的問(wèn)題篡帕。
from 語(yǔ)句潛在的陷阱
因?yàn)?from 語(yǔ)句會(huì)讓變量位置更隱秘和模糊,所以 form 語(yǔ)句可能會(huì)破壞命名空間拢军。如果使用 from 導(dǎo)入變量怔鳖,而那些變量碰巧和作用域中現(xiàn)有變量同名茉唉,變量就會(huì)被悄悄地覆蓋掉结执。使用簡(jiǎn)單的 import 語(yǔ)句就不會(huì)有這種問(wèn)題,因?yàn)槟阋欢ǖ猛ㄟ^(guò)模塊名才能獲取其屬性(變量名)懂傀。不過(guò)使用 from 時(shí)蜡感,只要你了解并預(yù)料到可能發(fā)生這種事,在實(shí)際情況下這就不是一個(gè)大問(wèn)題了铸敏,尤其當(dāng)你明確列出導(dǎo)入的變量名時(shí)(例如,from moudle import a, b, c)杈笔。
和 reload 調(diào)用同時(shí)使用時(shí),from 語(yǔ)句有比較嚴(yán)重的問(wèn)題球榆,因?yàn)閷?dǎo)入的變量名可能引用之前導(dǎo)入的對(duì)象禁筏。
簡(jiǎn)單模塊一般傾向于使用 import,而不是 from篱昔。多數(shù)的 from 語(yǔ)句是用于明確列舉出想要的變量始腾,而且限制在每個(gè)文件中只用一次 from * 形式空执。當(dāng)你必須使用兩個(gè)不同模塊內(nèi)定義的相同的變量名時(shí),才真的必須使用 import辨绊,這種情況下不能用 from(當(dāng)然你可以在 from 語(yǔ)句中使用 as 語(yǔ)句來(lái)個(gè)規(guī)避變量名沖突的問(wèn)題)。
(3)from - import * 形式
從一個(gè)模塊導(dǎo)入許多變量名時(shí)宣鄙,import 行會(huì)越來(lái)越長(zhǎng)默蚌,直到自動(dòng)換行冻晤,而且我們需要使用反斜杠字符 \
讓一條語(yǔ)句橫跨多行 敏簿。
from module import name1, name2, name3, name4,\
name5, name6, name7
你可以選擇使用多行的 from-import 語(yǔ)句:
from module import name1, name2, name3, name4
from module import name5, name6, name7
在 from 語(yǔ)句的 import 子句中,當(dāng)我們使用 * 時(shí)温数,會(huì)取得模塊頂層所有賦值的變量名的拷貝蜻势。從根本上來(lái)說(shuō),這就是把一個(gè)模塊的命名空間融入另一個(gè)模塊之中握玛;同樣地,實(shí)際效果就是可以讓我們少輸入一些代碼冕屯。from * 語(yǔ)句形式只能用在一個(gè)模塊文件的頂部,嘗試在類或函數(shù)定義中使用它將引發(fā) SyntaxError安聘。核心風(fēng)格: 限制使用 " from - import * "
在實(shí)踐中, 我們認(rèn)為 "from - import *" 不是良好的編程風(fēng)格瓢棒,因?yàn)樗?污染"當(dāng)前名稱空間,讓變量名難以理解脯宿。而且很可能覆蓋當(dāng)前名稱空間中現(xiàn)有的名字,尤其是在導(dǎo)入一個(gè)以上的模塊時(shí)榴芳。事實(shí)上,from * 形式會(huì)把一個(gè)命名空間融入到另一個(gè)翠语,所以會(huì)使得模塊的命名空間的分割特性失效财边。
如果某個(gè)模塊有很多要經(jīng)常訪問(wèn)的變量或者模塊的名字很長(zhǎng),這也不失為一個(gè)方便的好辦法酣难。我們只在兩種場(chǎng)合下建議使用這樣的方法,一個(gè)場(chǎng)合是:要使用的目標(biāo)模塊中的屬性非常多紧索,反復(fù)鍵入模塊名很不方便菜谣,例如 Tkinter (Python/Tk) 和 NumPy (Numeric Python) 模塊,可能還有 socket 模塊尾膊。另一個(gè)場(chǎng)合是在交互解釋器下,因?yàn)檫@樣可以減少輸入次數(shù)冈敛。
一般情況下,我們不提倡使用不再流行的 from module import * 語(yǔ)句 暮蹂。真正的 Python 程序員應(yīng)該使用 Python 的標(biāo)準(zhǔn)分組機(jī)制(圓括號(hào))來(lái)創(chuàng)建更合理更明確的多行導(dǎo)入語(yǔ)句癌压。
最小化 from * 的破壞:_x 和 __all__
把下劃線放在變量名前面(例如,_x)滩届,可以防止客戶端使用 from * 語(yǔ)句導(dǎo)入模塊名時(shí),把其中的那些變量名復(fù)制出去浅悉。這其實(shí)是為了對(duì)命名空間的破壞最小化而已。下劃線不是私有變量的聲明:你還是可以使用其他導(dǎo)入形式看見(jiàn)并修改這類變量名术健。
此外粘衬,你也可以在模塊頂層把變量名的字符串列表賦值給變量名 __all__ 咳促,以達(dá)到類似于 _x 命名慣例的隱藏效果勘伺。使用此功能時(shí),from * 語(yǔ)句只會(huì)把列在 __all__ 列表中的這些變量名賦值出來(lái)飞醉。事實(shí)上這和 x 慣例相反 __all時(shí)指出要復(fù)制的變量名,而_x 是指出不被復(fù)制的變量名轴术。Python 會(huì)先尋找模塊內(nèi)的 __all_ 列表;如果沒(méi)有定義的話逗栽,from * 就會(huì)復(fù)制出開頭沒(méi)有單下劃線的所有變量名失暂。
就像 _x 慣例一樣,__all__ 列表只對(duì) from * 語(yǔ)句這種形式有效弟塞,它并不是私有聲明。
(4)擴(kuò)展的導(dǎo)入語(yǔ)句(as)
有時(shí)候你導(dǎo)入的模塊名或是模塊屬性名稱已經(jīng)在你的程序中使用了想罕,或者你不想使用導(dǎo)入的名字,可能是它太長(zhǎng)不便輸入什么的按价。 這已經(jīng)成為 Python 程序員的一個(gè)普遍需求:使用自己想要的名字替換模塊的原始名稱笙瑟。使用擴(kuò)展的 as 子句,你就可以在導(dǎo)入的同時(shí)指定局部綁定名稱往枷。
import 語(yǔ)句和 from 語(yǔ)句都可以擴(kuò)展,讓模塊可以在腳本中給予不同的變量名秉宿。
import modulename as name
相當(dāng)于:
import modulename
name = modulename
del modulename
from modulename import attrname as name
相當(dāng)于:
from modulename import attrname
name = attrname
del attrname
這個(gè)擴(kuò)展功能很常用屯碴,替代變量名較長(zhǎng)的變量提供簡(jiǎn)短一些的同義詞,而且當(dāng)已在腳本中使用一個(gè)變量名使得執(zhí)行普通 import 語(yǔ)句會(huì)被覆蓋時(shí)导而,使用 as隔崎,就可避免變量名沖突韵丑。
4、模塊重載
在同一個(gè)進(jìn)程中模塊只在第一次導(dǎo)入時(shí)撵彻,加載和執(zhí)行該模塊的代碼。之后的導(dǎo)入只會(huì)使用已加載的模塊對(duì)象享幽,而不會(huì)重載或重新執(zhí)行文件的代碼拾弃。要強(qiáng)制使模塊重新載入并重新運(yùn)行摆霉,可以使用 reload() 函數(shù)豪椿。
reload()
reload() 函數(shù)位于Python中的 imp 模塊內(nèi)携栋,使用前必須先導(dǎo)入。它會(huì)強(qiáng)制已加載的模塊的代碼重新載入并重新執(zhí)行鸯隅。因?yàn)?reload() 期望得到的是對(duì)象向挖,在重載之前,模塊一定是已經(jīng)預(yù)先成功導(dǎo)入了何之。
重新執(zhí)行模塊文件的代碼會(huì)覆蓋其現(xiàn)有的命名空間。重載會(huì)影響所有使用 import 導(dǎo)入模塊的程序徊件,因?yàn)槭褂?import 的程序需要通過(guò)點(diǎn)號(hào)運(yùn)算符取出屬性,在重載后虱痕,使用的模塊對(duì)象變成了新的值辐赞。重載只會(huì)對(duì)重載后使用 from 語(yǔ)句導(dǎo)入模塊的程序造成影響。之前使用 from 來(lái)讀取屬性的客戶端并不會(huì)受到重載的影響占拍,那些程序引用的依然是重載前所取出的舊對(duì)象捎迫。
reload() 函數(shù)使得可以修改模塊程序的一些代碼表牢,而無(wú)須停止整個(gè)程序。因此崔兴,利用reload() ,可以立即看到對(duì)模塊的修改效果位谋。重載無(wú)法用于每種情況堰燎,但是能用時(shí),可縮短開發(fā)的流程秆剪。一般的用法是:導(dǎo)入一個(gè)模塊,在文本編輯器內(nèi)修改其源代碼仅讽,然后將其重載。當(dāng)調(diào)用 reload() 時(shí)饱岸,Python 會(huì)重讀模塊文件的源代碼徽千,重新執(zhí)行其頂層語(yǔ)句苫费。
因?yàn)?Python 是解釋性的(或多或少)罐栈,其實(shí)已經(jīng)避免了類似 C 語(yǔ)言程序執(zhí)行時(shí)所需的編譯連接步驟:在執(zhí)行程序?qū)霑r(shí),模塊會(huì)動(dòng)態(tài)加載琅翻。重載進(jìn)一步的提供了性能優(yōu)勢(shì)柑贞,讓你可以修改執(zhí)行中的程序的一部分,而不需要中止钧嘶。注意:reload() 當(dāng)前只能用在Python 編寫的模塊;用 C 這類語(yǔ)言編寫的編譯后的擴(kuò)展模塊也可在執(zhí)行中動(dòng)態(tài)加載,但無(wú)法重載空盼。
《Python基礎(chǔ)手冊(cè)》系列:
Python基礎(chǔ)手冊(cè) 1 —— Python語(yǔ)言介紹
Python基礎(chǔ)手冊(cè) 2 —— Python 環(huán)境搭建(Linux)
Python基礎(chǔ)手冊(cè) 3 —— Python解釋器
Python基礎(chǔ)手冊(cè) 4 —— 文本結(jié)構(gòu)
Python基礎(chǔ)手冊(cè) 5 —— 標(biāo)識(shí)符和關(guān)鍵字
Python基礎(chǔ)手冊(cè) 6 —— 操作符
Python基礎(chǔ)手冊(cè) 7 —— 內(nèi)建函數(shù)
Python基礎(chǔ)手冊(cè) 8 —— Python對(duì)象
Python基礎(chǔ)手冊(cè) 9 —— 數(shù)字類型
Python基礎(chǔ)手冊(cè)10 —— 序列(字符串)
Python基礎(chǔ)手冊(cè)11 —— 序列(元組&列表)
Python基礎(chǔ)手冊(cè)12 —— 序列(類型操作)
Python基礎(chǔ)手冊(cè)13 —— 映射(字典)
Python基礎(chǔ)手冊(cè)14 —— 集合
Python基礎(chǔ)手冊(cè)15 —— 解析
Python基礎(chǔ)手冊(cè)16 —— 文件
Python基礎(chǔ)手冊(cè)17 —— 簡(jiǎn)單語(yǔ)句
Python基礎(chǔ)手冊(cè)18 —— 復(fù)合語(yǔ)句(流程控制語(yǔ)句)
Python基礎(chǔ)手冊(cè)19 —— 迭代器
Python基礎(chǔ)手冊(cè)20 —— 生成器
Python基礎(chǔ)手冊(cè)21 —— 函數(shù)的定義
Python基礎(chǔ)手冊(cè)22 —— 函數(shù)的參數(shù)
Python基礎(chǔ)手冊(cè)23 —— 函數(shù)的調(diào)用
Python基礎(chǔ)手冊(cè)24 —— 函數(shù)中變量的作用域
Python基礎(chǔ)手冊(cè)25 —— 裝飾器
Python基礎(chǔ)手冊(cè)26 —— 錯(cuò)誤 & 異常
Python基礎(chǔ)手冊(cè)27 —— 模塊
Python基礎(chǔ)手冊(cè)28 —— 模塊的高級(jí)概念
Python基礎(chǔ)手冊(cè)29 —— 包