Python基礎概念_6_模組
7 模組
7.1 簡介
在上一章裡我們知道了如何建立和使用函式。如果你想要在其它程式中重用很多函式,那麼你該如何實現呢?你可能已經猜到了,答案是使用本章要講的模組。
模組可以讓你能夠有邏輯的組織你的Python程式碼段。通過把相關的程式碼分配到一個模組裡能讓你的程式碼更好用,更易懂。模組就是一個儲存了Python程式碼的檔案。模組可以定義函式,類和變數,當然模組裡也能包含可執行的程式碼。
如果python檔案中想引用另外個檔案,則可以使用import語句。這裡給個例子:
1) 假設我們將之前的函式getRectangleArea儲存成檔案MyTools.py。
defgetRectangleArea(length,breadth=2):
return "形參裡的長度是:"+str(length)+"\t形參裡的寬度是"+str(breadth)+"\n當前長方形的面積是:"+str(length*breadth)
注:這裡檔案型別要是utf-8編碼。
2)我們再新建個檔案加MyMain.py裡面的內容是呼叫MyTools.py裡定義的getRectangleArea函式。
import MyTools
print(MyTools.getRectangleArea(breadth=3,length=8))
這段程式碼是怎麼執行的呢?
首先Python遇到import會在.py檔案的當前目錄找MyTools.py這個檔案,
當執行到下一行時先會呼叫MyTools.py裡定義的getRectangleArea方法。
最後通過print打印出函式的返回值,也就是3*8=24。
注:這裡我們呼叫getRectangleArea函式時需要加上MyTools.不然會函式未定義的錯:
C:\PythonTest>python MyMain.py
Traceback (most recent call last):
File"MyMain.py", line 2, in <module>
print(getRectangleArea(breadth=4,length=9))
NameError: name 'getRectangleArea' is notdefined
3)我們在命令列裡通過python MyMain.py來驗證:
結果:
形參裡的長度是:8 形參裡的寬度是3
當前長方形的面積是:24
該語句是允許你從模組中一個指定的部分到當前名稱空間中,語法如下:
from modname import name1[, name2[, ...nameN]]
所以上一節我們可以這麼寫:
fromMyTools import getRectangleArea
print(getRectangleArea(breadth=4,length=9))
注:這裡我們不需要再加MyTools.getRectangleArea
如果想把一個模組的所有內容都匯入到當前的名稱空間就可以用該語句。
7.5 定位模組
當我們匯入一個模組,Python解析器對模組位置的搜尋順序是:
Ø 當前目錄
Ø PYTHONPATH下的每個目錄,這裡是Python的環境變數。
Ø 預設路徑,如:UNIX下一般為/usr/local/lib/python/
如果想了解一個模組定義的識別符號,可以通過dir函式進行檢視,這裡的識別符號有函式、類和變數。比如我們看系統內的sys模組,可以在python命令列裡這麼做:
>>>import sys
>>>dir(sys)
結果:
['__displayhook__','__doc__', '__excepthook__', '__interactivehook__', '__loade
r__', '__name__','__package__', '__spec__', '__stderr__', '__stdin__', '__stdou
t__','_clear_type_cache', '_current_frames', '_debugmallocstats', '_enablelegac
ywindowsfsencoding','_getframe', '_home', '_mercurial', '_xoptions', 'api_versi
on', 'argv','base_exec_prefix', 'base_prefix', 'builtin_module_names', 'byteord
er', 'call_tracing','callstats', 'copyright', 'displayhook', 'dllhandle', 'dont
_write_bytecode','exc_info', 'excepthook', 'exec_prefix', 'executable', 'exit',
'flags', 'float_info', 'float_repr_style','get_asyncgen_hooks', 'get_coroutine
_wrapper','getallocatedblocks', 'getcheckinterval', 'getdefaultencoding', 'getf
ilesystemencodeerrors','getfilesystemencoding', 'getprofile', 'getrecursionlimi
t', 'getrefcount','getsizeof', 'getswitchinterval', 'gettrace', 'getwindowsvers
ion', 'hash_info','hexversion', 'implementation', 'int_info', 'intern', 'is_fin
alizing', 'last_traceback','last_type', 'last_value', 'maxsize', 'maxunicode',
'meta_path','modules', 'path', 'path_hooks', 'path_importer_cache', 'platform',
'prefix', 'ps1', 'ps2', 'set_asyncgen_hooks','set_coroutine_wrapper', 'setchec
kinterval','setprofile', 'setrecursionlimit', 'setswitchinterval', 'settrace',
'stderr', 'stdin','stdout', 'thread_info', 'version', 'version_info', 'warnopti
ons', 'winver']
看上去有點複雜,這些都是Python系統預定義的函式或者類。我們還是以求面積的函式為例來講解下dir函式。不過在MyTools.py的getRectangleArea函式後再加個函式MyName,具體內容見下:
defgetRectangleArea(length,breadth=2):
return "形參裡的長度是:"+str(length)+"\t形參裡的寬度是"+str(breadth)+"\n當前長方形的面積是:"+str(length*breadth)
defgetMyName(firstName,LastName):
return "我的名字是"+firstName+"\t"+LastName
importMyTools
print(dir(MyTools))
結果:
我的名字是james bond
['__builtins__','__cached__', '__doc__', '__file__', '__loader__', '__name__',
'__package__','__spec__', 'getMyName','getRectangleArea']
注:這裡dir查到的函式就是getMyName和getRectangleArea。
7.7 模組的__name__
上一節我們執行dir函式查詢模組的識別符號時會看到__name__,它是每個模組內建的屬性,記錄著模組的名字。所以我們在執行MyMain.py時會有這樣的結果:
MyMain.py檔案內容:
importMyTools
print(MyTools.__name__)
print(__name__)
C:\PythonTest>python MyMain.py
結果:
MyTools
__main__
7.8 包
包是一個分層次的檔案目錄結構,它定義了一個由模組及子包下的模組的組成結構。眾所周知世界分5大洲,其中有亞洲,亞洲裡包含中國、印度,它們的首都分別是北京和新德里。我們就通過python程式碼結合這個層次來演示下包的概念,它們的層次可表示為下圖樹形結構:
C:\PythonTest>tree /f
注:
1這裡為了演示方便僅貼出了MyPackage.py和beijing.py的程式碼因為它們的內容大同小異。
2 這裡tree是windows/linux裡的命令,可以顯示目錄的樹形結構。通過上面可以看出資料夾china和india是一級的。
MyPackage.py程式碼:
importworld.asia.china.beijing as beijing
importworld.asia.india.newdelhi as newdelhi
importworld.asia.indiadesc as india
importworld.asia.chinadesc as china
importworld.asiadesc as asia
importworlddesc as world
if__name__ == '__main__':
print(beijing.getCurrentLevelName())
print(newdelhi.getCurrentLevelName())
print(india.getCurrentLevelName())
print(china.getCurrentLevelName())
print(asia.getCurrentLevelName())
print(world.getCurrentLevelName())
beijing.py程式碼:
defgetCurrentLevelName(LevelName='beijing'):
return "我在第"+str(4)+"層,我是:"+LevelName+"(北京)"+"。我的上層是china(中國)"
執行MyPackage.py
C:\PythonTest>python MyPackage.py
結果:
我在第4層,我是:beijing(北京)。我的上層是china(中國)
我在第4層,我是:newdelhi(新德里)。我的上層是india(印度)
我在第3層,我是:india(印度)我的上層是asia(亞洲)
我在第3層,我是:china(中國)我的上層是asia(亞洲)
我在第2層,我是:asia(亞洲)我的上層是world(世界)
我在第1層,我是:world(世界),我的上層沒了
注:
1需要注意個細節,包同一級內的資料夾裡不能再存在和包相同的py檔案,如果存在了也不能引用裡面的模組。
2 部分原始碼見下:chinadesc.py及indiadesc.py方法與外圍的worlddesc.py方法類似,列印的名字不同而已.以下以MyPackage.py和worlddesc.py為例:
MyPackage.py原始碼:
import world.asia.china.beijing as beijing
import world.asia.india.newdelhi as newdelhi
import world.asia.indiadesc as india
import world.asia.chinadesc as china
import world.asiadesc as asia
import worlddesc as world
if __name__ == '__main__':
print(beijing.getCurrentLevelName())
print(newdelhi.getCurrentLevelName())
print(india.getCurrentLevelName())
print(china.getCurrentLevelName())
print(asia.getCurrentLevelName())
print(world.getCurrentLevelName())
worlddesc.py原始碼:
def getCurrentLevelName(LevelName='world'): return "我在第"+str(1)+"層,我是:"+LevelName+"(世界)"+",我的上層沒了"
完整示例程式碼詳見資源:
http://download.csdn.net/detail/shenliang1985/9874376
7.9 總結
通過本章的學習我們知道了模組可更好將函式封裝起來,還知道了如何自己定義一個模組,以及自己通過包的方式管理模組,以及怎麼看模組的內建屬性。接下來,來了解另外個概念資料結構。