Lesson 9: 模組與套件
Last updated: 2022/10/11
多個「自訂函式」的集合
def 函式A():
...
return ...
def 函式B():
...
return ...
# 沒有主程式
原Python檔案
# 自訂函式
def Km2Mile(distance):
mile = distance/1.609
return mile
# 主程式開始
speed = Km2Mile(150)
print('%6.1f' % speed)
import converter # 匯入自訂模組
km = 100
mile = converter.Km2Mile(km) # 呼叫模組的功能
print('%d公里 =%8.2f英哩' % (km, mile))
僅保留函式
# 取任意名,例如:converter.py
# 提供公里轉英里的功能
def Km2Mile(distance):
mile = distance/1.609
return mile
# 沒有主程式
模組:converter.py
另建新檔寫主程式
使用模組功能
建立模組檔
import 模組名稱
模組名稱.函式名稱
新的主程式py檔
import converter # 匯入自訂模組
km = 100
mile = converter.Km2Mile(km) # 呼叫模組的功能
print('%d公里 =%8.2f英哩' % (km, mile))
模組: 功能函式儲存同一檔案, 供其他程式使用
方便重複使用
# 取任意名,例如:converter.py
# 提供公里轉英里的功能
def Km2Mile(distance):
mile = distance/1.609
return mile
模組:converter.py
作業1.py
import converter # 引入模組
while True:
km = int(input('輸入公里數(0程式結束):'))
if (km == 0):
break
mile = converter.Km2Mile(km) # 呼叫模組功能
print('%d公里 =%8.2f英哩' % (km, mile))
print('程式結束')
作業2.py
範例:實作模組,可以隨機回傳「剪刀」、「石頭」、「布」三者其中之一
import random # python常用模組
status = ['剪刀', '石頭', '布']
def guess():
"""提供guess功能, 回傳剪刀、石頭、布三者任一"""
return random.choice(status)
模組:guess.py
import guess # 引入模組
computer = guess.guess() # 呼叫guess()功能
print(computer)
範例主程式.py
練習:撰寫一模組rectangle.py,提供計算面積area(), perimeter()
def area(width, height):
# 計算面積
# return 面積
def perimeter(width, height):
# 計算周長
# return 周長
模組:rectangle.py
import rectangle
寬 = int(input('輸入四邊形寬:'))
高 = int(input('輸入四邊形高'))
面積 = rectangle.area(寬, 高)
周長 = rectangle.perimeter(寬, 高)
print('四邊形寬高為: %d x %d' % (寬, 高))
print('面積與周長為: %d, %d' % (面積, 周長))
練習主程式.py
def Menu(): # 印出預購折扣表
print('='*10)
print('1. 1杯無折扣')
print('2. 10杯62折')
print('3. 50杯58折')
print('4. 99杯53折')
print('0. 結束')
print('='*10)
def Total(數量, 單價, 折扣=1.0): # 計算總價與減價
減價 = 數量*單價*(1.0-折扣)
return 減價, 數量*單價*折扣 # 回傳 減價與總價
模組:sale.py
import 模組名稱
import sale
price = 45 # 單價45元
amount = [1, 10, 50, 99] # 杯數串列
折扣數 = [1.0, 0.62, 0.58, 0.53] # 折扣串列
sale.Menu()
decision = int(input('你的選擇是:'))
if decision>0 and decision<5:
save, total = sale.Total(amount[decision-1], price, 折扣數[decision-1])
print('購買數量 %d, 總價%d, 節省%d' % (amount[decision-1], total, save))
else:
print('選項輸入錯誤')
模組使用方法1
函式呼叫:模組名稱.函式名稱()
ex01.py
from 模組名稱 import 函式名稱
from sale import Total
from sale import Menu
price = 45 # 單價45元
amount = [1, 10, 50, 99] # 杯數串列
折扣數 = [1.0, 0.62, 0.58, 0.53] # 折扣串列
Menu()
decision = int(input('你的選擇是:'))
if decision>0 and decision<5:
save, total = Total(amount[decision-1], price, 折扣數[decision-1])
print('購買數量 %d, 總價%d, 節省%d' % (amount[decision-1], total, save))
else:
print('選項輸入錯誤')
模組使用方法2: 只引入特定函式
函式呼叫時,只需使用 函式名稱()
from 模組名稱 import 函式1, 函式2,...
from sale import Total, Menu
price = 45 # 單價45元
amount = [1, 10, 50, 99] # 杯數串列
折扣數 = [1.0, 0.62, 0.58, 0.53] # 折扣串列
Menu()
decision = int(input('你的選擇是:'))
if decision>0 and decision<5:
save, total = Total(amount[decision-1], price, 折扣數[decision-1])
print('購買數量 %d, 總價%d, 節省%d' % (amount[decision-1], total, save))
else:
print('選項輸入錯誤')
模組使用方法3: 引入多個函式
函式呼叫時,只需使用 函式名稱()
from 模組名稱 import *
from sale import *
price = 45 # 單價45元
amount = [1, 10, 50, 99] # 杯數串列
折扣數 = [1.0, 0.62, 0.58, 0.53] # 折扣串列
Menu()
decision = int(input('你的選擇是:'))
if decision>0 and decision<5:
save, total = Total(amount[decision-1], price, 折扣數[decision-1])
print('購買數量 %d, 總價%d, 節省%d' % (amount[decision-1], total, save))
else:
print('選項輸入錯誤')
模組使用方法4: 引入所有函式
函式呼叫時,只需使用 函式名稱()
from 模組名稱 import *
函式呼叫時,只需使用 函式名稱()
import 模組名稱
函式呼叫:模組名稱.函式名稱()
def area(width, height):
# 計算面積
# return 面積
def perimeter(width, height):
# 計算周長
# return 周長
模組:rectangle.py
import rectangle
寬 = int(input('輸入四邊形寬:'))
高 = int(input('輸入四邊形高'))
面積 = rectangle.area(寬, 高)
周長 = rectangle.perimeter(寬, 高)
print('四邊形寬高為: %d x %d' % (寬, 高))
print('面積與周長為: %d, %d' % (面積, 周長))
from rectangle import *
寬 = int(input('輸入四邊形寬:'))
高 = int(input('輸入四邊形高'))
面積 = area(寬, 高)
周長 = perimeter(寬, 高)
print('四邊形寬高為: %d x %d' % (寬, 高))
print('面積與周長為: %d, %d' % (面積, 周長))
ex02.py
ex02.py
寫法1
寫法2
練習:建立模組dice.py,提供一dice()功能,傳回擲出的點數(隨機產生1~6)
# dice.py模組
from random import choice
點數 = [1, 2, 3, 4, 5, 6]
def dice():
return choice(點數)
模組:dice.py
import dice # 引入模組dice.py
# 呼叫dice.dice(),共產生10次點數
for count in range(1,11):
print('第%d輪的點數是: %d' % (count, dice.dice()))
ex03.py
實作:樂透模組exlotto.py。該模組內有一個函式lotto,可以從1到n個數字中,取m個數字製作中獎號碼串列,回傳中獎號碼串列
# exlotto.py模組
from random import choice
def lotto(n, m):
"""n: 數字1到n,可以用range(1, n+1)建立"""
"""m: 取m個數字,但不可重複"""
...
模組:exlotto.py
另外撰寫主程式 hw6-1.py,呼叫上述模組的lotto(),並印出中獎號碼
# 函式用法提示1
from random import choice
數列 = [1,2 ,3, 4] # 任意數列
數值 = choice(數列) # 隨機挑出一個
# 函式用法提示2
數列 = [1,2 ,3, 4] # 任意數列
數列.remove(3) # 移除數列中第一個3
print(數列) # 印出[1,2,4]
import 模組名稱 as 替代名稱
函式呼叫:替代名稱.函式名稱()
import sale as s #用簡單名稱取代原先模組名稱
import random as r
...
sale.Menu()
....
r.choice()
練習:建立模組dice.py,提供一dice()功能,傳回擲出的點數(隨機產生1~6)
改用import ... as ...
# dice.py模組
from random import choice
點數 = [1, 2, 3, 4, 5, 6]
def dice():
return choice(點數)
模組:dice.py
import dice as d # 引入模組dice.py
# 呼叫dice.dice(),共產生10次點數
for count in range(1,11):
print('第%d輪的點數是: %d' % (count, d.dice()))
一個「資料夾」內包含多個模組,及一個獨立檔案__init__.py
套件
模組2
模組N
模組1
...
__init__.py
# 取任意名,例如:distance.py
# 提供公里轉英里的功能
def Km2Mile(distance):
mile = distance/1.609
return mile
# 沒有主程式
模組:distance.py
# 取任意名,例如:degree.py
# 提供華氏轉攝氏的功能
def c2f(degree):
f = degree * 1.8 + 32
return f
# 沒有主程式
模組:degree.py
__init__.py
資料夾: converter
套件:多個模組放在同一個資料夾下,並新增__init__.py
converter套件,內含兩個模組distance, degree
套件:多個模組放在同一個資料夾下,並新增__init__.py
game套件,內含兩個模組dice, poker
from 套件名稱 import 模組名稱
函式呼叫:模組名稱.函式名稱()
# 取任意名,例如:distance.py
# 提供公里轉英里的功能
def Km2Mile(distance):
mile = distance/1.609
return mile
# 沒有主程式
模組:distance.py
# 取任意名,例如:degree.py
# 提供華氏轉攝氏的功能
def c2f(degree):
f = degree * 1.8 + 32
return f
# 沒有主程式
模組:degree.py
__init__.py
資料夾: converter
from convert import distance, degree
print(distance.Km2Mile(100))
print(degree.c2f(10))
範例1.py
from 套件名稱 import 模組名稱
函式呼叫:模組名稱.函式名稱()
from random import choice
def dice():
return choice(range(1,7))
模組:dice.py
from random import choice
def poker():
a = ['C', 'H', 'D', 'S']
b = [1, 2, 3, 4, 5, 6, 7, 8, 9, 'T', 'J', 'Q', 'K']
return choice(a) + str(choice(b))
模組:poker.py
__init__.py
資料夾: game
from game import dice, poker
for i in range(2):
print(dice.dice())
print(poker.poker())
範例2.py
亂數(隨機數): 平均散佈在「某個區間」的數字
❶ randint(min, max): 隨機產生介於min與max之間的整數
import random
...
dice = random.randint(1,6) # 隨機產生1~6點
import random
...
poker = random.randint(0, 51) # 產生0~51之間的數字
花色 = poker // 13 # 整數除法-> 0~3, 0黑桃,1紅心...
點數 = (poker % 13) # 0~12 -> A,2,3,...10,J,Q,K
import porker
c, p = poker.pick()
print(f'抽到的牌是{c} {p}')
import random
花色 = ['黑桃', '紅心', '方塊', '梅花']
點數 = ['A','2','3','4','5','6','7','8','9','10','J','Q','K']
def pick():
'''挑一張牌'''
num = random.randint(1, 52) # 隨機挑一張
card = 花色[num // 13] # 整數除法結果為0,1,2,3
point = 點數[num % 13] # 餘數 0~12
return card, point
模組:poker.py
主程式:main01.py
import porker
for i in range(52):
c, p = poker.draw()
print(f'抽到的牌是{c} {p}')
import random
花色 = ['黑桃', '紅心', '方塊', '梅花']
點數 = ['A','2','3','4','5','6','7','8','9','10','J','Q','K']
folder = [i for i in range(52)] # 產生0~51的串列
def pick():
'''挑一張牌'''
num = random.randint(0, 51) # 隨機挑一張
card = 花色[num // 13] # 整數除法結果為0,1,2,3
point = 點數[num % 13] # 餘數 0~12
return card, point
def draw():
'''發牌'''
while True:
num = random.randint(0, 51) # 隨機挑一張
if num in folder: # 牌還在
card = 花色[num // 13] # 整數除法結果為0,1,2,3
point = 點數[num % 13] # 餘數 0~12
folder.remove(num)
print(folder)
break
return card, point
模組更新版:poker.py
主程式:main02.py
# 印出10個點數
import random
for i in range(1,11):
num = random.randint(1,6) # 隨機產生1~6點
print(num)
範例:印出10次擲骰子的點數
練習:統計骰子點數1~6各出現幾次
挑戰:如何累計次數,存在何處?可使用串列(list)
import random
擲骰子次數 = 100
統計串列 = [0] * 6 # 產生[0, 0, 0, 0, 0, 0]
for i in range(1, 擲骰子次數+1):
dice = random.randint(1, 6) # 擲骰子
統計串列[dice-1] += 1 # 統計
print(統計串列) # 印出統計結果
執行結果:[16, 22, 17, 7, 20, 18]
範例:猜數字遊戲-由亂數產生答案(介於1~100)
import random
answer = random.randint(1,100) # 產生答案
次數 = 0 # 猜測次數歸零
while True:
guess = int(input("輸入1~100之間的整數:"))
次數 += 1 # 猜測次數多1次
if (guess == answer):
print("你答對了!")
break
if (guess > answer):
print('猜小一點')
else:
print('猜大一點')
print('總共猜了%d次' % 次數)
練習:隨機產生2000張撲克牌,並統計每張撲克牌各出現幾次
印出 黑桃A: 38次, 黑桃2: 40次....
import random
...
poker = random.randint(0, 51) # 產生1~52
花色 = poker // 13 # 整數除法-> 0~3, 0黑桃,1紅心...
點數 = (poker % 13) # 0~12 -> A,2,3,...10,J,Q,K
提示:
❷ choice(串列名稱): 隨機從串列中回傳一個元素
import random
fruits = ['蘋果', '鳳梨', '香蕉', '芭樂']
def pick(): # 注意下一行的註解
'''隨機回傳水果的種類 '''
return random.choice(fruits)
import fruit
# 主程式
水果 = fruit.pick()
print(f'今天飯後水果是: {水果}')
模組:fruit.py
主程式:main.py
範例:網購T恤,T恤有紅藍綠黑白5種顏色,採隨機出貨,請在輸入數量後,印出出貨的數量與顏色
import random
顏色 = ['紅', '綠', '藍', '白', '黑']
統計 = dict() # 以字典統計數量:{'紅': 2, '白': 2, '黑': 1}
數量 = int(input('請輸入數量:'))
for i in range(數量):
挑選 = random.choice(顏色) # 隨機出貨
if (挑選 in 統計): # 顏色已在字典中
統計[挑選] += 1 # 加1
else: # 顏色不在字典中
統計[挑選] = 1 # 加入字典, 初值為1
# 輸出結果
print('總共買%d件' % 數量)
for key, value in 統計.items():
print("%s色有%d件" % (key, int(value)))
練習:請改寫下列統計骰子出現次數的範例,改用choice()
import random
擲骰子次數 = 100
統計串列 = [0] * 6 # 產生[0, 0, 0, 0, 0, 0]
for i in range(擲骰子次數):
dice = random.randint(1, 6) # 擲骰子
統計串列[dice-1] += 1 # 統計
print(統計串列) # 印出統計結果
時間模組: 可用來計算「程式執行的時間」、或抓取系統的「日期與時間」
日曆、時間
碼表
排程
❶ time(): 回傳自1970/1/1 00:00:00AM以來的秒數(UNIX紀元)
import time
seconds = float(time.time()) # 抓取系統當時的時間
print(f'自1970/1/1 00:00:00AM以來,過了{seconds:8.2f}秒')
import time
開始秒數 = float(time.time())
###
# 想要計算執行秒數的程式碼在此
###
結束秒數 = float(time.time())
print(f'執行時間 {結束秒數-開始秒數:8.2f}')
範例:修改「骰子點數出現次數」的範例,加上時間函數time(),最後印出程式執行所需的時間
import random, time
擲骰子次數 = 100
統計串列 = [0] * 6 # 產生[0, 0, 0, 0, 0, 0]
start = time.time()
for i in range(1, 擲骰子次數+1):
dice = random.randint(1, 6) # 擲骰子
統計串列[dice-1] += 1 # 統計
end = time.time()
print(f'執行時間是 {end-start:10.5f}')
print(統計串列) # 印出統計結果
範例:修改猜數字遊戲範例,觀察程式執行的時間
import random
answer = random.randint(1,100) # 產生答案
次數 = 0 # 猜測次數歸零
while True:
guess = int(input("輸入1~100之間的整數:"))
次數 += 1 # 猜測次數多1次
if (guess == answer):
print("你答對了!")
break
if (guess > answer):
print('猜小一點')
else:
print('猜大一點')
print('總共猜了%d次' % 次數)
練習:修改前頁範例,改為依序輸出100, 1000, 10000, 100000次的執行時間各為多少(在同一程式裡)
import random, time
# 可改為串列
擲骰子次數 = [100, 1000, 10000, 100000]
# 雙層for迴圈
# 外層處理次數
# 內層處理擲骰子, 與統計次數
#
import time
# 從10倒數到1
for i in range(10, 0, -1):
print(i)
time.sleep(1.0)
print('時間到')
❷ sleep(秒數): 讓程式工作暫停N秒鐘,可用於動畫設計
import time
import sys
# 從10倒數到1
for i in range(10, 0, -1):
print(str(i).zfill(2) + '\r', end='' )
time.sleep(1.0)
print('時間到')
範例:再搭配使用印出'\r'字元(歸位鍵),可做成倒數計時器
str(10).zfill(2) # 印出10
str(9).zfile(2) # 印出09
練習:輸入秒數,做成如上頁的倒數計時器,輸出格式為hh:mm:ss
# 提示:內建函式divmod(總秒數, 60) 可回傳'分','秒'
總秒數 = 12345
分鐘,秒數 = divmod(總秒數, 60)
小時,分鐘 = divmod(分鐘, 60)
print(str(小時), str(分鐘), str(秒數))
print(str(小時).zfill(2), str(分鐘).zfill(2), str(秒數).zfill(2))
3 25 45
03 25 45
❸localtime(): 回傳目前的時間結構資料串列。
import time
目前時間 = time.localtime()
print(目前時間)
time.struct_time(tm_year=2019, tm_mon=10, tm_mday=21, tm_hour=14, tm_min=54, tm_sec=34, tm_wday=0, tm_yday=294, tm_isdst=0)
import time
目前時間 = time.localtime()
print(目前時間) # 目前時間為一tuple
print('年:', 目前時間[0]) # 索引值0為年
print('月:', 目前時間[1]) # 索引值1為月
print('日:', 目前時間[2]) # 索引值2為日
print('時:', 目前時間[3]) # 索引值3為時
print('分:', 目前時間[4]) # 索引值4為分
print('秒:', 目前時間[5]) # 索引值5為秒
print('星期幾:', 目前時間[6]) # 0為星期一
print('第幾天:', 目前時間[7]) # 一年中的第幾天
print('夏令時間:', 目前時間[8]) # 0為非夏令時間
練習:使用localtime改寫倒數計時
import time
目前時間 = time.localtime()
print(目前時間)