1模塊
1.1Python中的模塊介紹和使用
有過C語(yǔ)言編程經(jīng)驗(yàn)的朋友都知道在C語(yǔ)言中如果要引用sqrt函數(shù),必須用語(yǔ)句#include
引入math.h這個(gè)頭文件,否則是無(wú)法正常進(jìn)行調(diào)用的。
那么在Python中,如果要引用一些其他的函數(shù),該怎么處理呢?
在Python中有一個(gè)概念叫做模塊(module),這個(gè)和C語(yǔ)言中的頭文件以及Java中的包很類似,比如在Python中要調(diào)用sqrt函數(shù),必須用import關(guān)鍵字引入math這個(gè)模塊,下面就來(lái)了解一下Python中的模塊。
說的通俗點(diǎn):模塊就好比是工具包,要想使用這個(gè)工具包中的工具(就好比函數(shù)),就需要導(dǎo)入這個(gè)模塊
1.1.1import
在Python中用關(guān)鍵字import來(lái)引入某個(gè)模塊,比如要引用模塊math,就可以在文件最開始的地方用import math來(lái)引入。
形如:
import module1,mudule2...
當(dāng)解釋器遇到import語(yǔ)句,如果模塊在當(dāng)前的搜索路徑就會(huì)被導(dǎo)入。
在調(diào)用math模塊中的函數(shù)時(shí),必須這樣引用:
模塊名.函數(shù)名
·想一想:
為什么必須加上模塊名調(diào)用呢?
·答:
因?yàn)榭赡艽嬖谶@樣一種情況:在多個(gè)模塊中含有相同名稱的函數(shù),此時(shí)如果只是通過函數(shù)名來(lái)調(diào)用,解釋器無(wú)法知道到底要調(diào)用哪個(gè)函數(shù)。所以如果像上述這樣引入模塊的時(shí)候,調(diào)用函數(shù)必須加上模塊名
importmath
#這樣會(huì)報(bào)錯(cuò)
printsqrt(2)
#這樣才能正確輸出結(jié)果
printmath.sqrt(2)
有時(shí)候我們只需要用到模塊中的某個(gè)函數(shù),只需要引入該函數(shù)即可,此時(shí)可以用下面方法實(shí)現(xiàn):
from模塊名import函數(shù)名1,函數(shù)名2....
不僅可以引入函數(shù),還可以引入一些全局變量、類等
注意:
o通過這種方式引入的時(shí)候,調(diào)用函數(shù)時(shí)只能給出函數(shù)名,不能給出模塊名,但是當(dāng)兩個(gè)模塊中含有相同名稱函數(shù)的時(shí)候,后面一次引入會(huì)覆蓋前一次引入。也就是說假如模塊A中有函數(shù)function( ),在模塊B中也有函數(shù)function(
),如果引入A中的function在先、B中的function在后,那么當(dāng)調(diào)用function函數(shù)的時(shí)候,是去執(zhí)行模塊B中的function函數(shù)。
o如果想一次性引入math中所有的東西,還可以通過from math import *來(lái)實(shí)現(xiàn)
1.1.2from…import
Python的from語(yǔ)句讓你從模塊中導(dǎo)入一個(gè)指定的部分到當(dāng)前命名空間中
語(yǔ)法如下:
frommodnameimportname1[, name2[, ... nameN]]
例如,要導(dǎo)入模塊fib的fibonacci函數(shù),使用如下語(yǔ)句:
fromfibimportfibonacci
注意
·不會(huì)把整個(gè)fib模塊導(dǎo)入到當(dāng)前的命名空間中,它只會(huì)將fib里的fibonacci單個(gè)引入
1.1.3from … import *
把一個(gè)模塊的所有內(nèi)容全都導(dǎo)入到當(dāng)前的命名空間也是可行的,只需使用如下聲明:
frommodnameimport*
注意
·這提供了一個(gè)簡(jiǎn)單的方法來(lái)導(dǎo)入一個(gè)模塊中的所有項(xiàng)目。然而這種聲明不該被過多地使用。
1.1.4as
In [1]: import time as tt
In [2]: time.sleep(1)
---------------------------------------------------------------------------
NameErrorTraceback (most recent call last)
in ()
----> 1 time.sleep(1)
NameError: name 'time' is not defined
In [3]:
In [3]:
In [3]: tt.sleep(1)
In [4]:
In [4]:
In [4]: from time import sleep as sp
In [5]: sleep(1)
---------------------------------------------------------------------------
NameErrorTraceback (most recent call last)
in ()
----> 1 sleep(1)
NameError: name 'sleep' is not defined
In [6]:
In [6]:
In [6]: sp(1)
In [7]:
1.1.5定位模塊
當(dāng)你導(dǎo)入一個(gè)模塊,Python解析器對(duì)模塊位置的搜索順序是:
1.當(dāng)前目錄
2.如果不在當(dāng)前目錄,Python則搜索在shell變量PYTHONPATH下的每個(gè)目錄。
3.如果都找不到,Python會(huì)察看默認(rèn)路徑。UNIX下,默認(rèn)路徑一般為/usr/local/lib/python/
4.模塊搜索路徑存儲(chǔ)在system模塊的sys.path變量中。變量里包含當(dāng)前目錄,PYTHONPATH和由安裝過程決定的默認(rèn)目錄。
1.2模塊制作
1.2.1定義自己的模塊
在Python中,每個(gè)Python文件都可以作為一個(gè)模塊,模塊的名字就是文件的名字。
比如有這樣一個(gè)文件test.py,在test.py中定義了函數(shù)add
test.py
defadd(a,b):
returna+b
1.2.2調(diào)用自己定義的模塊
那么在其他文件中就可以先import test,然后通過test.add(a,b)來(lái)調(diào)用了,當(dāng)然也可以通過from test import add來(lái)引入
main.py
importtest
result = test.add(11,22)
print(result)
1.2.3測(cè)試模塊
在實(shí)際開中,當(dāng)一個(gè)開發(fā)人員編寫完一個(gè)模塊后,為了讓模塊能夠在項(xiàng)目中達(dá)到想要的效果,這個(gè)開發(fā)人員會(huì)自行在py文件中添加一些測(cè)試信息,例如:
test.py
defadd(a,b):
returna+b
#用來(lái)進(jìn)行測(cè)試
ret = add(12,22)
print('int test.py file,,,,12+22=%d'%ret)
如果此時(shí),在其他py文件中引入了此文件的話,想想看,測(cè)試的那段代碼是否也會(huì)執(zhí)行呢!
main.py
importtest
result = test.add(11,22)
print(result)
至此,可發(fā)現(xiàn)test.py中的測(cè)試代碼,應(yīng)該是單獨(dú)執(zhí)行test.py文件時(shí)才應(yīng)該執(zhí)行的,不應(yīng)該是其他的文件中引用而執(zhí)行
為了解決這個(gè)問題,python在執(zhí)行一個(gè)文件時(shí)有個(gè)變量__name__
總結(jié):
·可以根據(jù)__name__變量的結(jié)果能夠判斷出,是直接執(zhí)行的python腳本還是被引入執(zhí)行的,從而能夠有選擇性的執(zhí)行測(cè)試代碼
·__name__如果寫在被直接運(yùn)行的主文件中,是”__main__”
·如果寫在被導(dǎo)入的文件中,運(yùn)行主文件的時(shí)候,導(dǎo)入文件中的__name__是”模塊的名字”
1.3模塊中的__all__
1.3.1沒有__all__
1.3.2模塊中有__all__
總結(jié)
·如果一個(gè)文件中有__all__變量,那么也就意味著這個(gè)變量中的元素,不會(huì)被from xxx import *時(shí)導(dǎo)入