2025年11月10日 星期一

[水井USR創新教材]Python一下用爬蟲技術取得環境開放式資料

API使用說明:https://data.moenv.gov.tw/paradigm

範例一:簡易介接

1
2
3
4
5
6
import requests
import urllib3

urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning)
r=requests.get('https://data.moenv.gov.tw/api/v2/acidr_p_01?format=json&offset=0&limit=5&api_key=KEY值請申請', verify=False)
print(r.text)

執行結果:
{
    "fields": [
        {
            "id": "siteid",
            "type": "text",
            "info": {
                "label": "測站代碼"
            }
        },
        {
            "id": "sitename",
            "type": "text",
            "info": {
                "label": "測站中文名稱"
            }
        },
<未完>

範例二:使用DataFrame

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
import requests
import urllib3
import pandas as pd
import json

urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning)
r=requests.get('https://data.moenv.gov.tw/api/v2/acidr_p_01?format=json&offset=0&limit=5&api_key=申請的KEY值', verify=False)
print(r.text)

data = json.loads(r.text) 
records = data.get("records", [])
df = pd.DataFrame(records)
print(df.head())
df_selected = df[[
    "sitename", "county", "township", "monitor_date",
    "item_name", "result_value", "item_unit"
]]

print(df_selected.head())

執行結果:



  siteid sitename site_ename  ... item_ename result_value item_unit
0     78       馬公     Magong  ...   RAIN_SUM            0        mm
1     77       金門     Kinmen  ...   RAIN_SUM            0        mm
2     75       馬祖      Matsu  ...   RAIN_SUM            0        mm
3     66       冬山   Dongshan  ...   RAIN_SUM            0        mm
4     64       陽明   Yangming  ...   RAIN_SUM            0        mm

[5 rows x 16 columns]
  sitename county township monitor_date item_name result_value item_unit
0       馬公    澎湖縣      馬公市     20211230      雨量累計            0        mm
1       金門    金門縣      金城鎮     20211230      雨量累計            0        mm
2       馬祖    連江縣      南竿鄉     20211230      雨量累計            0        mm
3       冬山    宜蘭縣      冬山鄉     20211230      雨量累計            0        mm
4       陽明    臺北市      北投區     20211230      雨量累計            0        mm

[水井USR創新教材]Python一下用爬蟲技術協助水井村漁民取得市場交易行情

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
import requests
import urllib3
import json

# 關閉 InsecureRequestWarning
urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning)

url = 'https://data.moa.gov.tw/Service/OpenData/FromM/AquaticTransData.aspx'
r = requests.get(url, verify=False)

# 檢查 HTTP 狀態
if r.status_code != 200:
    print(f"資料取得失敗,HTTP 狀態碼:{r.status_code}")
else:
    try:
        text = json.loads(r.text)
        for row in text:
            # 有些資料可能沒有「魚貨名稱」或「市場名稱」,需先檢查鍵存在
            if '魚貨名稱' in row and '市場名稱' in row:
                if '吳郭魚' in row['魚貨名稱'] and '斗南' in row['市場名稱']:
                    print('交易日期:' + str(row.get('交易日期', '無資料')))
                    print('品種代碼:' + str(row.get('品種代碼', '無資料')))
                    print('魚貨名稱:' + str(row.get('魚貨名稱', '無資料')))
                    print('市場名稱:' + str(row.get('市場名稱', '無資料')))
                    print('上價:' + str(row.get('上價', '無資料')))
                    print('中價:' + str(row.get('中價', '無資料')))
                    print('下價:' + str(row.get('下價', '無資料')))
                    print('交易量:' + str(row.get('交易量', '無資料')))
                    print('平均價:' + str(row.get('平均價', '無資料')))
                    print('-' * 40)
    except json.JSONDecodeError as e:
        print("JSON 解析錯誤:", e)
    except Exception as e:
        print("發生錯誤:", e)


執行結果: 交易日期:1141109 品種代碼:1011 魚貨名稱:吳郭魚 市場名稱:斗南 上價:76.0 中價:63.6 下價:51.9 交易量:1631.0 平均價:63.8 ---------------------------------------- 交易日期:1141108 品種代碼:1011 魚貨名稱:吳郭魚 市場名稱:斗南 上價:76.7 中價:74.8 下價:72.5 交易量:1751.3 平均價:74.7 ---------------------------------------- 交易日期:1141107 品種代碼:1011 魚貨名稱:吳郭魚 市場名稱:斗南 上價:76.0 中價:66.6 下價:52.0 交易量:1636.3 平均價:65.6 ---------------------------------------- 交易日期:1141106 品種代碼:1011 魚貨名稱:吳郭魚 市場名稱:斗南 上價:76.0 中價:67.2 下價:59.3 交易量:1643.7 平均價:67.4 ---------------------------------------- 交易日期:1141105 品種代碼:1011 魚貨名稱:吳郭魚 市場名稱:斗南 上價:76.0 中價:63.4 下價:56.0 交易量:1593.1 平均價:64.5 ---------------------------------------- 交易日期:1141104 品種代碼:1011 魚貨名稱:吳郭魚 市場名稱:斗南 上價:76.0 中價:70.8 下價:63.6 交易量:1812.5 平均價:70.4 ---------------------------------------- 交易日期:1141102 品種代碼:1011 魚貨名稱:吳郭魚 市場名稱:斗南 上價:76.0 中價:64.0 下價:48.8 交易量:1704.5 平均價:63.4 ---------------------------------------- 交易日期:1141101 品種代碼:1011 魚貨名稱:吳郭魚 市場名稱:斗南 上價:76.0 中價:69.5 下價:58.1 交易量:1790.1 平均價:68.5 ----------------------------------------

[水井USR創新教材]Python一下用水井村故事學會 locals() 和 globals()

以下資訊是由ChatGPT協助生成: 

在程式世界裡,

  • globals() 就像整個「水井村的地圖」🌏,記錄所有村子裡的名字(變數、函式、物件……)

  • locals() 就像「屋子裡的物品清單」🏠,只記錄某個房間(函式內部)的變數。

🏡範例 一、水井村全景地圖:globals()

水井村有許多居民與地標:烏龜、白馬、姻緣花。
這些都是「全域變數」,大家都能看到。

程式:
1
2
3
4
5
6
7
8
# 水井村的全景地圖
village = "水井村"
turtle = "烏龜"
horse = "白馬"
flower = "姻緣花"

print("=== 水井村的全景地圖(globals) ===")
print(globals().keys())  # 查看整個村子的地圖上有誰

執行結果:
=== 水井村的全景地圖(globals) ===
dict_keys(['__name__', '__doc__', '__package__', '__loader__', '__spec__', '__annotations__', '__builtins__', '__file__', 'village', 'turtle', 'horse', 'flower'])

💡說明:
globals() 會回傳一個字典(dict),裡面有所有全域變數的名字與內容。
在這裡,它就像是整座村莊的登記簿。

🕳️ 範例二、進入烏龜的房間:locals()

現在,我們走進烏龜的房間。
裡面有牠自己的小物品(在地變數),這些東西村外的人看不到。

程式:

1
2
3
4
5
6
7
def turtle_room():
    food = "萵苣葉"
    toy = "石頭球"
    print("=== 烏龜房間裡的物品(locals) ===")
    print(locals())  # 查看房間裡的變數有哪些

turtle_room()

執行結果:
=== 烏龜房間裡的物品(locals) ===
{'food': '萵苣葉', 'toy': '石頭球'}

💡說明:
locals() 只會顯示在函式內部定義的變數。
離開房間後,這些變數就不再存在。

🧭 範例三、結合使用:房間內外的界線
程式:
1
2
3
4
5
6
7
8
treasure = "金井水"

def white_horse():
    tool = "竹掃帚"
    print("房間內能看到 globals 嗎?", "treasure" in globals())
    print("房間內能看到 locals 嗎?", "tool" in locals())

white_horse()

執行結果:
房間內能看到 globals 嗎? True
房間內能看到 locals 嗎? True

🧠 意思是:
函式裡面可以看到全村的變數(globals())。
但全村看不到你房間裡的私人物品(locals())。

💬 結論整理
名稱 範圍 比喻 說明
globals() 全域範圍 🌏 水井村地圖 存放所有村莊共用的資源
locals() 區域範圍 🏠 烏龜房間 存放函式內部的私有變數
可視範圍 函式內可看全域,全域看不到區域 🚪 單向門 保護變數,避免混亂

🎯 延伸任務(課堂練習)

請同學完成:
定義一個 love_story() 函式,裡面有 boy = "白馬"、girl = "姻緣花"。
  1. 在函式中列印出 locals()。
  2. 在外部列印出 globals()。
  3. 思考:函式外部能看到 boy 和 girl 嗎?

[水井USR創新教材]Python一下用水井三寶認識 Python 的 os 模組



以下教材是用ChatGPT生成。

在程式的世界裡,os 模組就像是我們在電腦裡旅行時的「導遊」,幫我們找到路、開資料夾、搬東西、檢查有沒有東西存在。

我們來看看三位主角——烏龜、白馬、姻緣花——是怎麼幫助我們理解 os 模組的!

範例一:🐢 烏龜:穩重的導覽員(os.getcwd / os.chdir)

烏龜總是走得慢但很穩,它最擅長「知道自己在哪裡」。

程式碼:

1
2
3
4
5
6
7
8
import os

# 烏龜看看自己現在在哪個資料夾
print("烏龜現在在:", os.getcwd())

# 烏龜想要換到另一個資料夾
os.chdir("C:/Users")  # 換路徑
print("烏龜移動後的位置:", os.getcwd())
執行結果:
烏龜現在在: C:\Users\cheng-min\AppData\Local\Programs\Python\Python313
烏龜移動後的位置: C:\Users

🗣 烏龜的智慧:

「知道當前路徑,才能慢慢走向下一個目標。」

範例二:🐎 白馬:行動派的搬運工(os.listdir / os.mkdir / os.remove)

白馬速度快、效率高,最擅長整理與搬運檔案。
程式碼:
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
import os

# 白馬看看這裡有哪些東西
print("白馬看到的東西:", os.listdir())

# 白馬替主人開一個新資料夾
os.mkdir("姻緣花資料夾")

# 白馬幫忙確認檔案有沒有存在後再刪掉
if os.path.exists("舊檔案.txt"):
    os.remove("舊檔案.txt")

執行結果:
白馬看到的東西: ['AquaticTransData.docx', 'AquaticTransData.xlsx', 'DLLs', 'Doc', 'grades.xlsx', 'grades_final.xlsx', 'guess.py', 'include', 'Lib', 'libs', 'LICENSE.txt', 'NEWS.txt', 'ollama1.py', 'ollama2.py', 'ollama3.py', 'ollama4.py', 'open.py', 'open2.py', 'python.exe', 'python3.dll', 'python313.dll', 'pythonw.exe', 'Scripts', 'suijing_sanbao', 'tcl', 'template.docx', 'template.py', 'test.py', 'test2.py', 'ttsx.py', 'vcruntime140.dll', 'vcruntime140_1.dll', '__pycache__']

🗣 白馬的智慧:

「行動力就是力量!想整理資料,就用我的蹄子吧~」

範例三:🌸 姻緣花:串起緣分的橋樑(os.path.join / os.path.exists)

姻緣花最會「牽線」——她能把不同的路徑串起來,讓一切有緣相會。

程式:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
import os

# 姻緣花幫兩段路徑牽在一起
path = os.path.join("C:/Users", "Documents", "水井村")
print("姻緣花牽起的路徑:", path)

# 看看這條緣分路上是否真的存在
if os.path.exists(path):
    print("這條路是真的有緣~")
else:
    print("緣分還沒到,資料夾不存在。")

執行結果:
姻緣花牽起的路徑: C:/Users\Documents\水井村
緣分還沒到,資料夾不存在。

🗣 姻緣花的智慧:

「連結,是一切的開始。」

💡小結論

角色功能對應 os 模組函式
🐢 烏龜了解與改變當前位置os.getcwd()os.chdir()
🐎 白馬整理、建立與刪除資料os.listdir()os.mkdir()os.remove()
🌸 姻緣花串接路徑與檢查存在os.path.join()os.path.exists()

🎯延伸任務(適合課堂練習)

請同學們寫一個「水井三寶自動巡邏程式」:
  1. 讓烏龜顯示目前位置。
  2. 讓白馬建立一個新資料夾 三寶任務。
  3. 讓姻緣花檢查資料夾是否存在並印出結果。

2025年10月13日 星期一

[水井USR創新教材]Python一下用水井三寶來看字串正規表示式的用法



以下是用Grok AI生成。 

以「水井三寶」(烏龜、白馬、姻緣花)為主題,設計一個 Python 小範例,展示如何使用隨機密碼生成器來產生與水井三寶相關的密碼。這個範例會結合物件導向程式設計(OOP)和 Python 的 random 模組,生成帶有三寶特色的密碼(例如包含「烏龜」、「白馬」、「姻緣花」的主題詞,並混雜隨機字元)。我們會使用封裝來管理密碼生成邏輯,並透過繼承讓每個寶物有獨特的密碼風格。

情境設定

假設我們要為水井三寶的每種寶物生成專屬密碼:

  • 烏龜:密碼強調「長壽」,包含數字(年份)並較長。
  • 白馬:密碼強調「迅捷」,包含特殊字元(象徵速度)並中等長度。
  • 姻緣花:密碼強調「浪漫」,包含字母和愛心符號,較短但優雅。

每個密碼會結合寶物名稱、隨機字元(字母、數字、特殊符號),並確保安全性和隨機性。

範例程式碼

以下是一個完整的 Python 程式,展示如何用 OOP 和隨機模組生成水井三寶主題的密碼。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
import random
import string

class Treasure:
    """基類:定義水井三寶密碼生成器的共同行為"""
    def __init__(self, name):
        self.name = name
        self._charset = string.ascii_letters + string.digits + string.punctuation  # 基本字元集

    def generate_password(self, length=8):
        """生成隨機密碼,包含寶物名稱"""
        random_part = ''.join(random.choice(self._charset) for _ in range(length - len(self.name)))
        password = self.name + random_part
        # 打亂密碼字元
        password = ''.join(random.sample(password, len(password)))
        return password

class Turtle(Treasure):
    """烏龜:生成長壽主題的長密碼,強調數字"""
    def __init__(self):
        super().__init__("烏龜")
        self._charset = string.digits  # 烏龜密碼以數字為主

    def generate_password(self, length=12):
        """覆寫:生成12位密碼,包含至少4個數字"""
        random_part = ''.join(random.choice(self._charset) for _ in range(4))  # 4個數字
        extra_part = ''.join(random.choice(string.ascii_letters) for _ in range(length - 4 - len(self.name)))
        password = self.name + random_part + extra_part
        return ''.join(random.sample(password, len(password)))

class WhiteHorse(Treasure):
    """白馬:生成迅捷主題的密碼,包含特殊字元"""
    def __init__(self):
        super().__init__("白馬")
        self._charset = string.punctuation  # 白馬密碼以特殊字元為主

    def generate_password(self, length=10):
        """覆寫:生成10位密碼,包含至少3個特殊字元"""
        random_part = ''.join(random.choice(self._charset) for _ in range(3))  # 3個特殊字元
        extra_part = ''.join(random.choice(string.ascii_letters + string.digits) for _ in range(length - 3 - len(self.name)))
        password = self.name + random_part + extra_part
        return ''.join(random.sample(password, len(password)))

class MarriageFlower(Treasure):
    """姻緣花:生成浪漫主題的短密碼,包含愛心符號"""
    def __init__(self):
        super().__init__("姻緣花")
        self._charset = string.ascii_letters + "♥"  # 包含愛心符號

    def generate_password(self, length=8):
        """覆寫:生成8位密碼,包含至少1個愛心符號"""
        random_part = random.choice("♥")  # 至少1個愛心
        extra_part = ''.join(random.choice(string.ascii_letters) for _ in range(length - 1 - len(self.name)))
        password = self.name + random_part + extra_part
        return ''.join(random.sample(password, len(password)))

# 測試範例
if __name__ == "__main__":
    # 創建水井三寶實例
    turtle = Turtle()
    horse = WhiteHorse()
    flower = MarriageFlower()

    # 生成並展示密碼
    treasures = [turtle, horse, flower]
    for treasure in treasures:
        print(f"{treasure.name} 的密碼:{treasure.generate_password()}")

執行結果:
烏龜 的密碼:uY4龜8烏VcwU48
白馬 的密碼:v馬Gn白[X+'T
姻緣花 的密碼:a姻♥花Gqt緣

程式碼解析

  1. 正規表示式相關性
    • 雖然本題聚焦密碼生成,但可以延伸到正規表示式。例如,生成的密碼可透過 regex 驗證是否包含特定字元(例如 \d+ 檢查數字、[!@#$%^&*] 檢查特殊字元)。
    • 範例中未直接使用 regex,但可添加驗證(見下方擴展建議)。
  2. OOP 技術應用
    • 繼承:Turtle、WhiteHorse 和 MarriageFlower 繼承 Treasure,共享基本密碼生成邏輯。
    • 多型:每個子類別覆寫 generate_password,生成符合自身主題的密碼。
    • 封裝:_charset 是保護屬性,控制可用的字元集。
    • 類與實例屬性:name 是實例屬性,確保每個寶物有獨特名稱;_charset 在子類別中自訂。
  3. 隨機密碼生成
    • 使用 random.choice 從字元集中選取字元。
    • 使用 random.sample 打亂密碼字元,增加隨機性。
    • 每個寶物有不同長度和字元偏好:
      • 烏龜:12位,強調數字。
      • 白馬:10位,包含特殊字元。
      • 姻緣花:8位,包含愛心符號 ♥。
  4. 安全考量
    • 密碼包含寶物名稱和隨機字元,並透過 random.sample 打亂,避免可預測性。
    • 真實應用中應使用 secrets 模組(更安全),但為簡單起見這裡用 random。

[水井USR創新教材]Python一下用水井三寶來看字串正規表示式的用法

圖:2025/10/13 在竹山鎮小鎮文創的協助下,尚虎雲在台西客運中展出作品,水井三寶是其中一件作品。

以下是採Grok AI生成的。 

以「水井三寶」(烏龜、白馬、姻緣花)為主題,設計一個 Python 小範例來展示正規表示式(Regular Expression, regex)的應用。這個範例會結合物件導向程式設計(OOP)和正規表示式,聚焦於如何使用 re 模組來處理與水井三寶相關的文字資料。每個寶物會有一個專屬的正規表示式模式,用於解析特定格式的吉祥訊息,並展示 OOP 的封裝特性來管理正規表示式邏輯。

情境設定

假設我們有一段文字,包含水井三寶的吉祥訊息,例如:

  • 「烏龜祝福:長壽100年」
  • 「白馬祝福:奔馳500公里」
  • 「姻緣花祝福:愛情99朵」 我們希望用正規表示式提取每個寶物的名稱和數值(例如年數、公里數、朵數),並透過類來管理這些模式和處理邏輯。

範例程式碼

以下是一個完整的 Python 範例,結合正規表示式和 OOP,並使用「水井三寶」來解析吉祥訊息。程式碼使用封裝來管理正規表示式,並提供簡單的處理方法。


 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
import re

class Treasure:
    """基類:定義水井三寶的共同行為"""
    def __init__(self, name):
        self.name = name
        self._pattern = None  # 保護屬性:正規表示式模式

    def extract_value(self, message):
        """提取訊息中的數值,使用正規表示式"""
        if not self._pattern:
            return f"{self.name} 尚未定義正規表示式!"
        match = re.match(self._pattern, message)
        if match:
            return f"{self.name} 提取到:{match.group(1)}"
        return f"{self.name} 無法解析訊息:{message}"

class Turtle(Treasure):
    """烏龜:解析 '長壽X年' 的訊息"""
    def __init__(self):
        super().__init__("烏龜")
        # 正規表示式:匹配 "烏龜祝福:長壽數字年"
        self._pattern = r"烏龜祝福:長壽(\d+)年"

class WhiteHorse(Treasure):
    """白馬:解析 '奔馳X公里' 的訊息"""
    def __init__(self):
        super().__init__("白馬")
        # 正規表示式:匹配 "白馬祝福:奔馳數字公里"
        self._pattern = r"白馬祝福:奔馳(\d+)公里"

class MarriageFlower(Treasure):
    """姻緣花:解析 '愛情X朵' 的訊息"""
    def __init__(self):
        super().__init__("姻緣花")
        # 正規表示式:匹配 "姻緣花祝福:愛情數字朵"
        self._pattern = r"姻緣花祝福:愛情(\d+)朵"

# 測試範例
if __name__ == "__main__":
    # 創建水井三寶實例
    turtle = Turtle()
    horse = WhiteHorse()
    flower = MarriageFlower()

    # 測試訊息
    messages = [
        "烏龜祝福:長壽100年",
        "白馬祝福:奔馳500公里",
        "姻緣花祝福:愛情99朵",
        "烏龜祝福:無效訊息",
    ]

    # 遍歷寶物和訊息,展示正規表示式提取
    treasures = [turtle, horse, flower]
    for treasure in treasures:
        print(f"\n測試 {treasure.name}:")
        for msg in messages:
            print(treasure.extract_value(msg))

執行結果:
測試 烏龜:
烏龜 提取到:100
烏龜 無法解析訊息:白馬祝福:奔馳500公里
烏龜 無法解析訊息:姻緣花祝福:愛情99朵
烏龜 無法解析訊息:烏龜祝福:無效訊息

測試 白馬:
白馬 無法解析訊息:烏龜祝福:長壽100年
白馬 提取到:500
白馬 無法解析訊息:姻緣花祝福:愛情99朵
白馬 無法解析訊息:烏龜祝福:無效訊息

測試 姻緣花:
姻緣花 無法解析訊息:烏龜祝福:長壽100年
姻緣花 無法解析訊息:白馬祝福:奔馳500公里
姻緣花 提取到:99
姻緣花 無法解析訊息:烏龜祝福:無效訊息

程式碼解析

  1. 正規表示式(Regex)應用
    • 每個子類定義專屬的正規表示式模式,儲存在 _pattern 中:
      • 烏龜:r"烏龜祝福:長壽(\d+)年" 提取年數(例如 "100")。
      • 白馬:r"白馬祝福:奔馳(\d+)公里" 提取公里數(例如 "500")。
      • 姻緣花:r"姻緣花祝福:愛情(\d+)朵" 提取朵數(例如 "99")。
    • 使用 re.match 檢查訊息是否符合模式,並提取括號 (\d+) 中的數字。
  2. 封裝(Encapsulation)
    • _pattern 是保護屬性,儲存每個寶物的正規表示式模式,外部無法直接修改。
    • extract_value 方法封裝了正規表示式的處理邏輯,提供統一的介面。
  3. 繼承(Inheritance)
    • Treasure 是基礎類別,定義了共用的 name 和 extract_value 方法。
    • Turtle、WhiteHorse 和 MarriageFlower 繼承 Treasure,並在 __init__ 中設定各自的正規表示式模式。
  4. 正規表示式的簡單說明
    • \d+:匹配一個或多個數字。
    • ():捕獲括號內的內容,供 match.group(1) 提取。
    • re.match:從字串開頭匹配,確保訊息格式正確。

技術亮點

  • 正規表示式與 OOP 的結合:每個寶物類負責自己的正規表示式模式,符合單一職責原則。
  • 封裝:正規表示式模式和提取邏輯被封裝在類內,外部只需呼叫 extract_value。
  • 可擴展性:可以輕鬆新增其他寶物類,只需定義新的正規表示式模式。

2025年10月6日 星期一

[水井USR創新教材]Python一下用水井三寶來設計例外的範例

 

以下資訊是由AI工具協助生成

範例一:烏龜(Turtle) - 風水能量過載例外

文化背景:烏龜代表穩定的風水能量,但能量過高可能「破壞平衡」,就像風水過旺不利環境穩定。

情境:烏龜的能量(energy)有限制,超過 1000 會引發自訂例外,模擬風水能量過載。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
class TurtleEnergyOverloadError(Exception):
    """自訂例外:烏龜能量過載"""
    pass

class Turtle:
    def __init__(self, energy=100):
        self.__energy = energy

    def recharge(self, amount):
        try:
            if amount < 0:
                raise ValueError("能量增量不能為負!")
            new_energy = self.__energy + amount
            if new_energy > 1000:
                raise TurtleEnergyOverloadError("烏龜能量過載,風水失衡!")
            self.__energy = new_energy
            return f"烏龜能量充滿:{self.__energy}"
        except TurtleEnergyOverloadError as e:
            return f"錯誤:{e}"
        except ValueError as e:
            return f"錯誤:{e}"

    def get_energy(self):
        return self.__energy

turtle = Turtle(energy=900)
print(turtle.recharge(50))   # 成功:烏龜能量充滿:950
print(turtle.recharge(100))  # 錯誤:烏龜能量過載,風水失衡!
print(turtle.recharge(-10))  # 錯誤:能量增量不能為負!

執行結果:
烏龜能量充滿:950
錯誤:烏龜能量過載,風水失衡!
錯誤:能量增量不能為負!

例外特性

  • 自訂例外:TurtleEnergyOverloadError 是自訂的例外類,模擬風水能量過載。
  • 多重例外處理:捕捉 ValueError(負值輸入)和自訂的 TurtleEnergyOverloadError,展示如何處理不同類型的錯誤。
  • 文化連結:烏龜的能量限制反映風水需要平衡的理念,過高能量會引發「失衡」。

範例二:白馬(WhiteHorse) - 好運耗盡例外
文化背景:白馬是李府千歲的座騎,象徵好運,但好運可能會因過度使用而「耗盡」。 情境:白馬有「好運點數」(luck_points),每次祈福(bless)消耗 10 點,若點數低於 0,則拋出例外。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
class LuckExhaustedError(Exception):
    """自訂例外:白馬好運耗盡"""
    pass

class Treasure:
    def bless(self):
        return "寶物帶來吉祥!"

class WhiteHorse(Treasure):
    def __init__(self, luck_points=100):
        self.luck_points = luck_points

    def bless(self):
        try:
            if self.luck_points <= 0:
                raise LuckExhaustedError("白馬好運已耗盡,請稍後再試!")
            self.luck_points -= 10
            return super().bless() + f" 白馬帶來好運!剩餘好運點數:{self.luck_points}"
        except LuckExhaustedError as e:
            return f"錯誤:{e}"

    def ride(self):
        return "白馬奔馳,風水順暢!"

horse = WhiteHorse(luck_points=20)
print(horse.bless())  # 成功:寶物帶來吉祥! 白馬帶來好運!剩餘好運點數:10
print(horse.bless())  # 成功:寶物帶來吉祥! 白馬帶來好運!剩餘好運點數:0
print(horse.bless())  # 錯誤:白馬好運已耗盡,請稍後再試!

執行結果:
寶物帶來吉祥! 白馬帶來好運!剩餘好運點數:10
寶物帶來吉祥! 白馬帶來好運!剩餘好運點數:0
錯誤:白馬好運已耗盡,請稍後再試!

例外特性:

自訂例外:LuckExhaustedError 表示白馬好運耗盡,模擬資源有限的情境。
繼承與例外:白馬繼承自 Treasure,並在 bless 方法中加入例外處理,展示 OOP 與例外的結合。
文化連結:好運點數耗盡反映白馬塑像消失的傳說,提醒好運需珍惜。

範例三:姻緣花(MarriageFlower) - 無效祈求者例外
文化背景:姻緣花(百年雞蛋花樹)象徵好姻緣,村裡女性常祈求好姻緣,但若祈求者不符合條件(例如名字無效),祈求失敗。
情境:姻緣花的 pray 方法要求祈求者名字為非空字串,否則拋出例外。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
class InvalidPrayError(Exception):
    """自訂例外:無效的祈求者"""
    pass

class MarriageFlower:
    def bloom(self):
        return "姻緣花開,庄內好姻緣!"

    def pray(self, person):
        try:
            if not person or not isinstance(person, str):
                raise InvalidPrayError("祈求者名字無效,需為非空字串!")
            return f"{person} 向姻緣花祈求,好姻緣即將到來!"
        except InvalidPrayError as e:
            return f"錯誤:{e}"

flower = MarriageFlower()
print(flower.pray("小明"))  # 成功:小明 向姻緣花祈求,好姻緣即將到來!
print(flower.pray(""))      # 錯誤:祈求者名字無效,需為非空字串!
print(flower.pray(123))     # 錯誤:祈求者名字無效,需為非空字串!

執行結果:
小明 向姻緣花祈求,好姻緣即將到來!
錯誤:祈求者名字無效,需為非空字串!
錯誤:祈求者名字無效,需為非空字串!

例外特性

  • 自訂例外:InvalidPrayError 用於檢查無效輸入,模擬姻緣祈求的條件限制。
  • 輸入驗證:檢查 person 是否為非空字串,展示如何在例外處理中進行輸入驗證。
  • 文化連結:姻緣花祈求需「真誠」(有效名字),反映文化中對姻緣的尊重。

2025年10月5日 星期日

[水井USR創新教材]Python一下用水井三寶來說明模組的用法

 

以上範例是由AI工成生成

範例一:水井三寶猜猜看

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
import random

def water_well_guess():
    # 水井三寶
    treasures = ["烏龜", "白馬", "姻緣花"]
    # 使用亂數選擇一個寶物
    selected_treasure = random.choice(treasures)
    return selected_treasure

# 測試函數
for _ in range(5):  # 模擬抽取 5 次
    result = water_well_guess()
    print(f"你從水井三寶中抽到:{result}")

執行結果:
你從水井三寶中抽到:白馬
你從水井三寶中抽到:姻緣花
你從水井三寶中抽到:白馬
你從水井三寶中抽到:白馬
你從水井三寶中抽到:白馬

範例二:水井三寶模 匯入整個模組
模組:guess.py
1
2
3
4
5
6
7
8
import random

def water_well_guess():
    # 水井三寶
    treasures = ["烏龜", "白馬", "姻緣花"]
    # 使用亂數選擇一個寶物
    selected_treasure = random.choice(treasures)
    return selected_treasure

測試:test.py
1
2
3
4
5
6
import guess 

# 測試函數
for _ in range(5):  # 模擬抽取 5 次
    result = guess.water_well_guess()
    print(f"你從水井三寶中抽到:{result}")

執行結果:
你從水井三寶中抽到:烏龜
你從水井三寶中抽到:姻緣花
你從水井三寶中抽到:烏龜
你從水井三寶中抽到:姻緣花
你從水井三寶中抽到:姻緣花

範例三:水井三寶模組 匯入想要的函式
模組程式請參考範例二
測試:test.py
1
2
3
4
5
6
from guess import water_well_guess 

# 測試函數
for _ in range(5):  # 模擬抽取 5 次
    result = water_well_guess()
    print(f"你從水井三寶中抽到:{result}")

執行結果:
你從水井三寶中抽到:姻緣花
你從水井三寶中抽到:烏龜
你從水井三寶中抽到:烏龜
你從水井三寶中抽到:烏龜
你從水井三寶中抽到:姻緣花

2025年10月3日 星期五

[水井USR創新教材]Python一下用水井三寶來說明類別的重要概念



本篇文章用「水井三寶」(烏龜、白馬、姻緣花)為主題,展示了 Python 類的七大核心技術:

  • 封裝:保護烏龜的能量值。
  • 繼承:白馬繼承寶物基類的吉祥能力。
  • 多型:烏龜和姻緣花用不同方式「說話」。
  • 類與實例屬性:共享「水井吉祥」,每個寶物有獨特名稱。
  • 特殊方法:姻緣花自訂顯示和加法。
  • 類方法與靜態方法:白馬的召喚和速度計算。
  • 屬性管理:控制烏龜年齡的存取。
以下程式是用Grok產生。

範例一:封裝(Encapsulation)

封裝保護物件內部資料,限制外部直接存取。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
class Turtle:
    def __init__(self, name):
        self.__energy = 100  # 私有屬性:能量值
        self.name = name

    def get_energy(self):  # 公開方法存取
        return self.__energy

    def use_energy(self, amount):
        if amount > 0:
            self.__energy -= amount
            return f"{self.name} 使用 {amount} 能量,剩餘 {self.__energy}"
        return "無效的能量消耗!"

# 測試
t = Turtle("烏龜")
print(t.get_energy())  # 輸出: 100
print(t.use_energy(20))  # 輸出: 烏龜 使用 20 能量,剩餘 80
# print(t.__energy)  # 錯誤!無法直接存取私有屬性

執行結果:

100 烏龜 使用 20 能量,剩餘 80

解釋:__energy 是私有屬性,外部無法直接存取,只能透過 get_energy 和 use_energy 方法控制,展現封裝保護資料的能力。

範例二:繼承(Inheritance)

繼承讓子類重用父類的屬性和方法。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
class Treasure:
    def __init__(self, name):
        self.name = name

    def bless(self):
        return f"{self.name} 帶來吉祥!"

class WhiteHorse(Treasure):  # 繼承 Treasure
    def gallop(self):  # 子類專屬方法
        return f"{self.name} 飛馳千里!"

# 測試
horse = WhiteHorse("白馬")
print(horse.bless())  # 輸出: 白馬 帶來吉祥!(來自父類)
print(horse.gallop())  # 輸出: 白馬 飛馳千里!(子類專有)

執行結果:
白馬 帶來吉祥!
白馬 飛馳千里!

解釋:WhiteHorse 繼承 Treasure,可直接使用父類的 bless 方法,並新增自己的 gallop 方法,展示程式碼重用。

範例三:多型(Polymorphism)
多型允許不同類的物件以統一方式處理不同行為。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
class Treasure:
    def speak(self):
        pass  # 抽象方法,子類需實現

class Turtle(Treasure):
    def speak(self):
        return "烏龜:穩重長壽!"

class MarriageFlower(Treasure):
    def speak(self):
        return "姻緣花:愛情綻放!"

# 測試
treasures = [Turtle(), MarriageFlower()]
for t in treasures:
    print(t.speak())  # 輸出: 烏龜:穩重長壽! 和 姻緣花:愛情綻放!

執行結果:
烏龜:穩重長壽!
姻緣花:愛情綻放!
解釋:Turtle 和 MarriageFlower 都實現了 speak 方法,但行為不同。透過統一的 speak() 呼叫展現多型。

範例四:類與實例屬性(Class and Instance Attributes)

類屬性共享於所有實例,實例屬性獨立於每個物件。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
class Treasure:
    shared_blessing = "水井吉祥"  # 類屬性

    def __init__(self, name):
        self.name = name  # 實例屬性

    def describe(self):
        return f"{self.name} 擁有 {Treasure.shared_blessing}"

# 測試
t1 = Treasure("烏龜")
t2 = Treasure("白馬")
print(t1.describe())  # 輸出: 烏龜 擁有 水井吉祥
print(t2.describe())  # 輸出: 白馬 擁有 水井吉祥
Treasure.shared_blessing = "三寶輝煌"  # 修改類屬性
print(t1.describe())  # 輸出: 烏龜 擁有 三寶輝煌

執行結果:

烏龜 擁有 水井吉祥 白馬 擁有 水井吉祥 烏龜 擁有 三寶輝煌

解釋:shared_blessing 是類屬性,所有實例共享,修改它會影響所有物件;name 是實例屬性,各物件獨立。

範例五:特殊方法(Magic/Dunder Methods)

特殊方法自訂物件行為,如字串表示或運算。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
class MarriageFlower:
    def __init__(self, beauty):
        self.beauty = beauty

    def __str__(self):  # 自訂字串表示
        return f"姻緣花 美麗值: {self.beauty}"

    def __add__(self, other):  # 自訂加法
        total_beauty = self.beauty + other.beauty
        return MarriageFlower(total_beauty)

# 測試
f1 = MarriageFlower(10)
f2 = MarriageFlower(20)
print(f1)  # 輸出: 姻緣花 美麗值: 10
combined = f1 + f2
print(combined)  # 輸出: 姻緣花 美麗值: 30

執行結果:

姻緣花 美麗值: 10 姻緣花 美麗值: 30

解釋:__str__ 自訂 print 輸出;__add__ 讓 + 運算符合併兩朵姻緣花的美麗值,展示特殊方法的靈活性。

範例六:類方法與靜態方法(Class Methods and Static Methods)

類方法操作類本身,靜態方法獨立於類和實例。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
class WhiteHorse:
    @classmethod
    def summon(cls, name):  # 類方法
        return cls()

    @staticmethod
    def calculate_speed(distance, time):  # 靜態方法
        return f"白馬速度:{distance / time} 公里/小時"

    def __init__(self):
        self.name = "白馬"

# 測試
horse = WhiteHorse.summon("白馬")  # 類方法創建實例
print(WhiteHorse.calculate_speed(100, 2))  # 輸出: 白馬速度:50.0 公里/小時

執行結果:
白馬速度:50.0 公里/小時

解釋:@classmethod 的 summon 使用 cls 創建實例;@staticmethod 的 calculate_speed 獨立計算,無需實例。

範例七:屬性管理(Property Decorators)

屬性裝飾器將方法偽裝成屬性,控制存取。


 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
class Turtle:
    def __init__(self, age):
        self._age = age  # 保護屬性

    @property
    def age(self):  # getter
        return self._age

    @age.setter
    def age(self, value):  # setter
        if value < 0:
            raise ValueError("烏龜年齡不能為負!")
        self._age = value

# 測試
t = Turtle(50)
print(t.age)  # 輸出: 50
t.age = 100  # 使用 setter 修改
print(t.age)  # 輸出: 100
# t.age = -10  # 會拋出錯誤

執行結果:

50 100

解釋:@property 讓 _age 像屬性一樣存取;@age.setter 控制賦值,確保年齡不為負數。