模組與 import 陳述式
- 用多個檔案來建立並使用 Python 程式
- 所謂的模組(module),只是一個 Python 程式檔
- 按層次來架構
- 程式碼:資料類型(單字) → 陳述式(句子) → 函式(段落) → 模組(章節)
- 在程式中,參考其他模組的程式
- 就像比喻:在本書中參考第八章解釋
- 要參考其他模組的程式:使用 import 陳述式 → 讓你的程式使用「被匯入模組裡面的程式與變數」
匯入模組
- import 陳述式最簡單的用法是:import module
- 其中 moudle 是其他的 Python 檔,不包括 .py 副檔名
【案例一】模擬一個氣象站,並印出一個氣象報告
1.撰寫主程式、獨立的模組
- 用一個主程式來印出報告
- 以及一個獨立的模組 → 裡面有一個函式,會回傳供報告使用的氣象狀況
主程式(weatherman.py)
在 import 陳述式之後,主程式就可以使用模組(report.py)內的所有東西,只要在它的名稱前面使用「模組名稱.」 (report.)
import 模組名稱
description = 模組名稱.get_description()
print("文字:", description)
#在 import 陳述式之後,主程式就可以使用 report.py 內的所有東西,只要在它的名稱前面使用 report. 即可
import report # 匯入整個 report 模組
description = report.get_description() # 匯入整個 report 模組,但需要在 get_description() 前面使用 report.
print("Today's weather:", description)
模組(report.py)
用模組的名稱來限定模組的內容,所以「可以避免名稱衝突」。別的地方也有可能會有 get_description() 函式,但不會不小心呼叫它
def get_description():
"""文字"""
from 模組名稱 import 函式名稱
串列名稱 = ['字串1', '字串2', '字串3', '字串4', '字串5', '字串6']
return 函式名稱(串列名稱)
def get_description(): # see the docstring
"""Return random weather, just like the pros"""
from random import choice
possibilities = ['rain', 'snow', 'sleet', 'fog', 'sun', 'who knows']
return choice(possibilities)
2.將兩個檔案放在同一個目錄下
- 指示 Python 將 weatherman.py 當成主程式來執行 → 它會存取 report 模組,並執行它的 get_description()函式
- 主程式會取回並印出的東西 → 編寫 get_description() 來回傳一串串列內的隨機結果
python weatherman.py
Today's weather: sleet
python weatherman.py
Today's weather: who knows
python weatherman.py
Today's weather: rain
在兩個不同的地方 → 使用 import
- 匯入主程式 weatherman.py(模組 report的主程式)
import report
- 在模組檔 report.py 裡面,get_description()函式 → 由「Python 標準隨機模組」匯入「choice函式」
from random import choice
以兩種不同的方式 → 使用 imports
- 主程式 → 呼叫 import report,接著執行 report.get_description()
- report.py 裡面 → get_decription() 呼叫 from random import choice,接著執行 choice(possibilities)
【案例二】
- 一個函式裡面,知道這裡沒有其他叫做「choice」的東西
- 直接從「random 模組(Python 內建標準模組庫)」匯入「choice() 函式」
- 採取下列方式來「編寫函式」→ 它會「回傳隨機結果」
「函式內」匯入模組 v.s. 「函式外」匯入模組
- 「函式內」匯入模組:只會在有限的範圍內使用它,就可在裡面匯入
- 「函式外」匯入模組:
- 要匯入的程式會在許多地方用到,就必須考慮在函式外面匯入它
- 有些人喜歡將所有的 import 放在檔案的開頭,清楚地展示程式間的關係
- 這兩種方式都是可行的
「函式內」匯入模組
- 如同許多其他程式部分,請挑選你最容易理解的方式
- 以模組來指定名稱(模組名稱.函式名稱)比較安全,但需要打較多字
- 這些 get_description()範例展示該匯入什麼,但沒有展示從哪裡匯入,它們都在函式裡呼叫 import
def get_description():
import 模組名稱
串列名稱 = ['字串1', '字串2', '字串3', '字串4', '字串5', '字串6']
return 模組名稱.函式名稱(串列名稱)
>>> def get_description():
import random
possibilities = ['rain', 'snow', 'sleet', 'fog', 'sun', 'who knows']
return random.choice(possibilities) # 以模組來指定名稱(random.choice)比較安全,但需要打較多字
>>> get_description()
'rain'
>>> get_description()
'snow'
「函式外」匯入模組
- 以上這些 get_description()範例展示該匯入什麼,但沒有展示從哪裡匯入,它們都在函式裡呼叫 import
- 也可以在「函式外」匯入「模組」
>>> import 模組名稱
>>> def get_description():
串列名稱 = ['字串1', '字串2', '字串3', '字串4', '字串5', '字串6']
return 模組名稱.函式名稱(串列名稱)
>>> import random # 也可以在函式外面匯入 random
>>> def get_description():
possibilities = ['rain', 'snow', 'sleet', 'fog', 'sun', 'who knows']
return random.choice(possibilities)
>>> get_description()
'snow'
>>> get_description()
'rain'
用其他的名稱來匯入模組
- 在 weatherman.py 主程式中,呼叫了 import report
- 如果有「其他的模組」使用「相同的名稱」,或想要使用「有助記憶」或「簡短名稱」時,該怎麼做?可以用別名來匯入
import 模組名稱 as 別名
description = 別名.get_description()
print("文字:", description)
import report as wr
description = wr.get_description()
print("Today's weather:", description)
只匯入模組內你想要的東西
在 Python 中,可以匯入模組的一或多個部分。每一個部分都可以「保留它原本名稱」,也可以給它一個「別名」
【範例】
# 匯入模組的 get_description()
from 模組名稱 import get_description
description = get_description()
print("文字:", description)
# 用別名來匯入
from 模組名稱 import get_description as 別名
description = 別名()
print("文字:", description)
# 首先,用原始名稱來匯入 report 模組的 get_description()
from report import get_description
description = get_description()
print("Today's weather:", description)
#接著,用 do_it 來匯入它
from report import get_description as do_it
description = do_it()
print("Today's weather:", description)
模組搜尋路徑
- Python 會去哪裡尋找要匯入的檔案?
- 使用「sys 標準模組」的「path 變數」內的一串「目錄名稱串列」,以及「ZIP 保存檔案(archive files)」
- 可以存取與修改這個串列
- 以下是在自己的 Mac 上,Python 3.6 的 sys.path 的值:
>>> import sys
>>> for place in sys.path:
print(place)
# 前面一開始的空白是一個空字串'',代表目前的目錄
/Library/Frameworks/Python.framework/Versions/3.6/lib/python36.zip
/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6
/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/lib-dynload
/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/site-packages
- 如果 sys.path 的第一行是 ' ',當試著匯入時,Python 會先查看目前的目錄 → 例如:import report 會尋找 report.py
- 會使用第一個找到的對象 → 例如:如果定義一個名叫 random 的模組,而且它的「搜尋路徑的位置」在「標準程式庫」之前,你就無法存取標準程式庫的 random 了