老男人開始學(xué)python之什么是模塊、包裂七、庫皆看?

在上一篇《老男人開始學(xué)python之Flask中的“Hello World”》中,雖然只按照教程寫了幾行短短的代碼背零,但是對于初學(xué)者的我來說就產(chǎn)生了一些疑問腰吟,有一些不明白的地方?

  1. 為什么文件名是“__init__.py”?
  2. __name__”是什么?
  3. from ... import ... 是什么意思毛雇?
  4. form ... import ... 和 import ...的區(qū)別是什么嫉称?

帶著問題去看了Python基礎(chǔ)教程模塊一節(jié)記錄總結(jié)一下。
參考教程:
廖雪峰:模塊灵疮、使用模塊织阅、安裝第三方模塊
鏈接:http://www.liaoxuefeng.com/

一、什么是模塊震捣、包荔棉、庫?

| Module(模塊)| Package(包)| Library(庫)|
| --------------------- | :------------------ | --------------- -: |
| 一個(gè).py文件就稱之為一個(gè)模塊(Module)| 只要包含__init__.py文件的文件夾就叫做包| 參考其他編程語言的說法蒿赢。就是指Python中完成一定功能的代碼集合润樱,供用戶使用的代碼組合。在python中是包和模塊的形式 | | abc.py模塊名就是abc诉植;|1.init.py文件必須存在祥国,否則就是一個(gè)文件夾;2.init.py文件可以為空晾腔,也可以有python代碼舌稀;3. 可以有多級層次結(jié)構(gòu)包含多個(gè)模塊或子包組成;4.init.py`文件本身就是一個(gè)模塊灼擂,模塊名就是包含它的文件夾的名稱壁查; |例如常說的第三方庫,是否可以簡單理解為包含多個(gè)Package(包)完成某功能的一個(gè)代碼集合 |

1.Package 包中都可以包含什么剔应?

F:\pythontest\test2.py             # test2模塊
F:\pythontest\test3                # test3文件夾中包含__init__.py文件睡腿,因此是一個(gè)包;
│  a.py                            # test3.a模塊峻贮;
│  b.py                            # test3.b模塊席怪; 
│  __init__.py                     # 也是一個(gè)模塊,名稱是:test3
│
├─b                                # 包含2個(gè)模塊的一個(gè)【文件夾】纤控,但是名稱和test3.b名稱同名了挂捻,該【文件夾】下的模塊能正常使用嗎?如果這里是個(gè)同名的子包呢船万?
│      a.py
│      b.py
│
├─c                                # 一個(gè)空【文件夾】
├─d                                # 因?yàn)榘琠_init__.py文件刻撒,因此是一個(gè)子包                 
│      a.py                        # 模塊名:test3.d.a
│      b.py                        # 模塊名:test3.d.a
│      __init__.py                 # 模塊名:test3.d  
│
└─e                                # 包含2個(gè)模塊的一個(gè)【文件夾】,該文件夾下的2個(gè)模塊能用嗎耿导?
        a.py                       # 暫認(rèn)為模塊名為:test3.e.a
        b.py                       # 暫認(rèn)為模塊名為:test3.e.b

如上所示声怔,一個(gè)包中可以包含:模塊(a、b)舱呻、包含模塊的文件夾(b醋火、e)、空文件夾(c)、子包(d)胎撇。

【說明】到了這里解決了第1個(gè)問題介粘,為什么文件名是“__init__.py”,因?yàn)樗且粋€(gè)Package(包)晚树;

下邊做一些測試:

#F:\pythontest\test3\a.py代碼如下:
def a():
    return "my name is 'a'"
#F:\pythontest\test3\b.py代碼如下:
def b():
    return "my name is 'b'"
#F:\pythontest\test3\b\a.py代碼如下:
def a():
    return "我是B文件夾下的 'a'"
#F:\pythontest\test3\b\b.py代碼如下:
def b():
    return "我是B文件夾下的 'b'"
#F:\pythontest\test3\d\a.py代碼如下:
def a():
    return "我是D子包中的 'a'"
#F:\pythontest\test3\d\b.py代碼如下:
def b():
    return "我是D子包中的 'b'"

__init__.py 文件全部為空姻采,F:\pythontest\test2.py文件中代碼分別為如下幾種情況的執(zhí)行結(jié)果:

-----------------------------------------------------------------------------------
import test3
x = test3.a.a()
print (x)


#執(zhí)行結(jié)果:
F:\pythontest>flask\Scripts\python.exe test2.py
Traceback (most recent call last):
  File "test2.py", line 2, in <module>
    x = test3.a.a()
AttributeError: 'module' object has no attribute 'a'

【總結(jié)】:因?yàn)閷?dǎo)入的模塊名為test3,也就是test3文件夾下的`__init__.py `文件爵憎,而該文件為空慨亲,所以找不到test3.a模塊中的a函數(shù);

-----------------------------------------------------------------------------------

使用import test3.a 導(dǎo)入test3.a模塊宝鼓,即test3文件夾下的a.py文件刑棵,就可以正常執(zhí)行:

import test3.a
x = test3.a.a()
print (x)

#執(zhí)行結(jié)果:
F:\pythontest>flask\Scripts\python.exe test2.py
my name is 'a'

-----------------------------------------------------------------------------------
#代碼如下:
import test3.b
x = test3.b.b()
print (x)
#執(zhí)行結(jié)果:
F:\pythontest>flask\Scripts\python.exe test2.py
my name is 'b'

#代碼更改如下:測試導(dǎo)入b文件夾中的b模塊
import test3.b.b
x = test3.b.b.b()
print (x)

#執(zhí)行結(jié)果:沒有模塊test3.b.b,test3.b不是一個(gè)包愚铡;
F:\pythontest>flask\Scripts\python.exe test2.py
Traceback (most recent call last):
  File "<frozen importlib._bootstrap>", line 2218, in _find_and_load_unlocked
AttributeError: 'module' object has no attribute '__path__'

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "test2.py", line 1, in <module>
    import test3.b.b
ImportError: No module named 'test3.b.b'; 'test3.b' is not a package

-----------------------------------------------------------------------------------
如果給b文件夾下放一個(gè)空__init__.py文件蛉签,這時(shí)候b文件夾就成了test3的一個(gè)子包則:
import test3.b
x = test3.b.b()
print (x)

#執(zhí)行結(jié)果:
F:\pythontest>flask\Scripts\python.exe test2.py
Traceback (most recent call last):
  File "test2.py", line 2, in <module>
    x = test3.b.b()
AttributeError: 'module' object has no attribute 'b'

【總結(jié)】因?yàn)閷?dǎo)入test3.b模塊的時(shí)候?qū)嶋H上b子包把test3.b模塊覆蓋了,實(shí)際上導(dǎo)入的是b文件夾中的__init__.py文件沥寥,而該文件為空碍舍,因此找不到b函數(shù);

#更改代碼如下:導(dǎo)入test3.b模塊邑雅,即test3\b\__init__.py
import test3.b
x = test3.b.a.a()
print (x)

#同時(shí)修改test3\b\__init__.py文件代碼如下:
import test3.b.a
#執(zhí)行結(jié)果:
F:\pythontest>flask\Scripts\python.exe test2.py
我是B文件夾下的 'a'

這個(gè)時(shí)候就是test3\b\__init__.py文件中導(dǎo)入了test3.b.a模塊片橡,然后在test2.py文件中導(dǎo)入了test3.b模塊即test3\b\__init__.py文件,換句話說就是在test3\b\__init__.py文件中引入了test3\b\a.py文件淮野,然后在test2.py文件中又引入了test3\b\__init__.py文件捧书,因此a.py中的a函數(shù)能被正常執(zhí)行。

-----------------------------------------------------------------------------------
#最后來看看e文件夾中的模塊文件能否被正常導(dǎo)入并使用模塊中的函數(shù)骤星?
代碼如下:
import test3.e.a
x = test3.e.a.a()
print (x)

#執(zhí)行結(jié)果:
F:\pythontest>flask\Scripts\python.exe test2.py
我是E文件夾下的 'a'模塊

從執(zhí)行結(jié)果來看经瓷,是可以正常運(yùn)行的。

更改一下代碼:
import test3.e
x = test3.e.a.a()
print (x)
執(zhí)行結(jié)果:
F:\pythontest>flask\Scripts\python.exe test2.py
Traceback (most recent call last):
  File "test2.py", line 2, in <module>
    x = test3.e.a.a()
AttributeError: 'module' object has no attribute 'a'

從以上兩例測試洞难,可以看到雖然e只是個(gè)文件夾不是子包舆吮,但是該文件夾下的模塊文件依然可以被導(dǎo)入。

上邊的兩個(gè)問題:

  1. 含2個(gè)模塊的一個(gè)【文件夾】廊营,但是名稱和test3.b名稱同名了歪泳,該【文件夾】下的模塊能正常使用嗎萝勤?如果這里是個(gè)同名的子包呢露筒?

    如果在test3包中,含有一個(gè)b.py和一個(gè)b文件夾敌卓,則b.py文件(模塊)可以被導(dǎo)入慎式,而b文件夾中的.py文件不能被導(dǎo)入;
    如果b文件夾是一個(gè)子包,則子包覆蓋b.py瘪吏;
    【注意】不要重名癣防,以免混淆!

  2. 文件夾e掌眠,不是子包蕾盯,該文件下包含2個(gè).py文件(模塊),該文件夾下的2個(gè)模塊能用嗎蓝丙?

    可以被導(dǎo)入使用级遭。這是為什么呢?

二渺尘、如何使用Module(模塊)挫鸽?

import 命令為導(dǎo)入Module(模塊)命令,而Module指的就是一個(gè).py文件鸥跟,其實(shí)就可以認(rèn)為是在一個(gè).py文件中引入另外一個(gè).py文件丢郊。

1. 使用導(dǎo)入Module(模塊)命令import

有幾種格式:

命令 解釋
import module 導(dǎo)入單個(gè)模塊
import module as name 導(dǎo)入單個(gè)模塊并重命名
import moudule1, moudule2,module3,... 一次導(dǎo)入多個(gè)模塊
import moudule1 as name1,module2 as name2,... 一次導(dǎo)入多個(gè)模塊并重命名

一般在文件首部導(dǎo)入所有模塊,推薦順序如下:

python標(biāo)準(zhǔn)庫
第三方模塊
應(yīng)用程序自定義模塊

2. 使用from...import...語句導(dǎo)入模塊的屬性(變量医咨、函數(shù)枫匾、對象)

命令 解釋
from module import name1,name2,name3 單行導(dǎo)入
from module import name1,name2,\ name3 多行導(dǎo)入
from module import * 導(dǎo)入全部屬性,一般不推薦使用腋逆,適合模塊中變量名很長和很多的情況婿牍。容易覆蓋當(dāng)前命名空間中現(xiàn)有的名字

當(dāng)試圖加載一個(gè)模塊的時(shí)候,Python會在指定的路徑下搜索對應(yīng)的.py文件惩歉,如果找不到等脂,就會報(bào)錯(cuò)。

默認(rèn)情況下,Python解釋器會搜索當(dāng)前文件夾、所有已安裝的內(nèi)置模塊和第三方模塊耳贬,搜索路徑存放在sys模塊的path變量中呐萌。

有兩種方法修改搜索路徑:
一是直接修改sys.path,添加要搜索的文件夾:sys.path.append('路徑')

第二種方法是設(shè)置環(huán)境變量PYTHONPATH曹货,該環(huán)境變量的內(nèi)容會被自動(dòng)添加到模塊搜索路徑中。設(shè)置方式與設(shè)置Path環(huán)境變量類似。注意只需要添加你自己的搜索路徑模软,Python自己本身的搜索路徑不受影響。

模塊被導(dǎo)入時(shí)饮潦,加載的時(shí)候模塊頂層代碼會被執(zhí)行燃异,一個(gè)模塊無論被導(dǎo)入多少次,只加載一次继蜡,可以防止多次導(dǎo)入時(shí)代碼被多次執(zhí)行回俐。

內(nèi)建函數(shù)reload可以重新導(dǎo)入一個(gè)已經(jīng)存在的模塊逛腿。

三、 “__name__”是什么仅颇?

簡單的說:
1.如果模塊(就是一個(gè).py)文件是直接執(zhí)行的单默,則__name__值就等于__main__
2.如果模塊是被導(dǎo)入的時(shí)候忘瓦,__name__的值就是模塊名搁廓;

#test_name2.py 代碼為:
def test_name2():                                # 定義一個(gè)函數(shù)test_name2
    b = __name__                                 # 將__name__賦值給變量b
    return b                                     # 函數(shù)返回變量b的值
if __name__ == "__main__":                       # 如果__name__ 等于字符串__main__ 就可以認(rèn)為是直接執(zhí)行的test_name2.py文件,則打印test_name2()函數(shù)的返回值耕皮;
    print (test_name2())

#test_name1.py 代碼為:

import test_name2                                # 導(dǎo)入模塊 test_name2
print (test_name2.test_name2())                  # 打印test_name2模塊中的test_name2函數(shù)值枚抵;

直接執(zhí)行test_name2的結(jié)果:結(jié)果為__main__
F:\pythontest>flask\Scripts\python.exe test_name2.py
__main__

直接執(zhí)行test_name1的結(jié)果:結(jié)果為模塊名
F:\pythontest>flask\Scripts\python.exe test_name1.py
test_name2

可做調(diào)試代碼用;
參考:
python:淺析python 中name = 'main' 的作用
python中name的使用

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末明场,一起剝皮案震驚了整個(gè)濱河市汽摹,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌苦锨,老刑警劉巖逼泣,帶你破解...
    沈念sama閱讀 206,311評論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異舟舒,居然都是意外死亡拉庶,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,339評論 2 382
  • 文/潘曉璐 我一進(jìn)店門秃励,熙熙樓的掌柜王于貴愁眉苦臉地迎上來氏仗,“玉大人,你說我怎么就攤上這事夺鲜〗远” “怎么了?”我有些...
    開封第一講書人閱讀 152,671評論 0 342
  • 文/不壞的土叔 我叫張陵币励,是天一觀的道長慷蠕。 經(jīng)常有香客問我,道長食呻,這世上最難降的妖魔是什么流炕? 我笑而不...
    開封第一講書人閱讀 55,252評論 1 279
  • 正文 為了忘掉前任,我火速辦了婚禮仅胞,結(jié)果婚禮上每辟,老公的妹妹穿的比我還像新娘。我一直安慰自己干旧,他們只是感情好渠欺,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,253評論 5 371
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著莱革,像睡著了一般峻堰。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上盅视,一...
    開封第一講書人閱讀 49,031評論 1 285
  • 那天捐名,我揣著相機(jī)與錄音,去河邊找鬼闹击。 笑死镶蹋,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的赏半。 我是一名探鬼主播贺归,決...
    沈念sama閱讀 38,340評論 3 399
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼断箫!你這毒婦竟也來了拂酣?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 36,973評論 0 259
  • 序言:老撾萬榮一對情侶失蹤仲义,失蹤者是張志新(化名)和其女友劉穎婶熬,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體埃撵,經(jīng)...
    沈念sama閱讀 43,466評論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡赵颅,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 35,937評論 2 323
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了暂刘。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片饺谬。...
    茶點(diǎn)故事閱讀 38,039評論 1 333
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖谣拣,靈堂內(nèi)的尸體忽然破棺而出募寨,到底是詐尸還是另有隱情,我是刑警寧澤森缠,帶...
    沈念sama閱讀 33,701評論 4 323
  • 正文 年R本政府宣布绪商,位于F島的核電站,受9級特大地震影響辅鲸,放射性物質(zhì)發(fā)生泄漏格郁。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,254評論 3 307
  • 文/蒙蒙 一独悴、第九天 我趴在偏房一處隱蔽的房頂上張望例书。 院中可真熱鬧,春花似錦刻炒、人聲如沸决采。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,259評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽树瞭。三九已至拇厢,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間晒喷,已是汗流浹背孝偎。 一陣腳步聲響...
    開封第一講書人閱讀 31,485評論 1 262
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留凉敲,地道東北人衣盾。 一個(gè)月前我還...
    沈念sama閱讀 45,497評論 2 354
  • 正文 我出身青樓,卻偏偏與公主長得像爷抓,于是被迫代替她去往敵國和親势决。 傳聞我的和親對象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,786評論 2 345

推薦閱讀更多精彩內(nèi)容