iT邦幫忙

2025 iThome 鐵人賽

DAY 5
0
生成式 AI

一塊一塊拼湊的 AI 樂高世界之旅系列 第 5

Day 5:函式、參數、回傳值與文件字串

  • 分享至 

  • xImage
  •  

前言

前幾天我們已經學會了如何存資料、做運算,以及用條件判斷與迴圈來控制流程。不過,如果程式越寫越大,一直重複貼相似的程式碼,不僅難以維護,也容易出錯。這時候,就需要用到 函式(Function)

函式的角色就像是一個「工具」或「機器」:

  • 你給它材料(引數),它會依照設計好的方式處理,最後再把結果交給你(回傳值)。
  • 這樣一來,程式不但更乾淨,而且可以重複使用,做到「寫一次,用很多次」。

在日常生活中:

  • 微波爐就像一個函式,放進食物(引數),按下按鈕,會加熱後交還(回傳值)。
  • 自動販賣機也是函式,投錢並選擇飲料(引數),它吐出一瓶飲料(回傳值)。

今天會學到:

  1. 函式的定義與呼叫 —— 如何建立自己的小工具。
  2. 參數與引數的差別 —— 清楚知道「設計工具」和「使用工具」的不同。
  3. 回傳值與 return —— 如何讓函式把結果交回來。
  4. 多種參數技巧 —— 預設值、*args**kwargs
  5. 文件字串(docstring) —— 幫函式加上說明文件,讓別人一看就懂用途。
  6. 常見錯誤與陷阱 —— 例如忘記 return,或使用錯誤的預設值。
  7. 實作練習 —— 透過小工具函式庫與題目練習,將概念轉成實力。

學會函式之後,程式就能更有架構,並且開始具備「模組化思維」,這也是邁向大型專案開發的重要基礎。


函式的定義與呼叫

# 定義一個函式(Function):加總兩數
def add(a, b):             # a, b 是[參數]
    result = a + b
    return result          # 傳出[回傳值]

# 呼叫函式,給予[引數]
print(add(3, 5))           # 輸出:8

https://ithelp.ithome.com.tw/upload/images/20250919/20161224HiTE4afd1r.png

重點記憶def 定義函式,return 把資料傳出


參數與引數的差別

名稱 定義位置 舉例
參數 函式「定義」時 def add(a, b)
引數 函式「呼叫」時 add(3, 5)

回傳值與 return

def square(x):         # x 是[參數]
    return x * x       # 傳出[回傳值]

y = square(4)          # y 得到 16
print(y)               # 輸出:16

❗ 如果沒寫 return,會默認回傳 None


多種參數技巧(預設值、*args**kwargs

預設參數值

def greet(name="小明"):
    print(f"哈囉,{name}!")

greet("阿華")    # 傳入引數
greet()          # 使用預設值

-- 若有印引數,則程式會採用引數阿華,若無,則使用預設的小明
https://ithelp.ithome.com.tw/upload/images/20250919/20161224nQ8cGKruYq.png

可變位置參數:*args

def total(*args):    # args 會收集所有位置引數成為 tuple
    return sum(args)

print(total(1, 2, 3))    # 輸出:6
print(total(1, 2, 3, 4, 5))    # 輸出:15

可變關鍵字參數:**kwargs

def profile(**kwargs):   # kwargs 會收集所有關鍵字引數成為 dict
    for k, v in kwargs.items():
        print(f"{k}:{v}")

profile(name="小美", age=18)
# 輸出:
# name:小美
# age:18

常見錯誤與陷阱

1. 漏寫 return

def bad_add(a, b):
    result = a + b
    # 忘記寫 return
print(bad_add(3,5)) # 輸出 None,如圖1

def good_add(a, b):
    result = a + b
    return result    # 正確回傳結果
print(good_add(3, 5))  # 輸出 8,如圖2

-- 圖1:
https://ithelp.ithome.com.tw/upload/images/20250919/201612243G6HKbFvJo.png--
圖2:
https://ithelp.ithome.com.tw/upload/images/20250919/20161224lUMp9UVUUR.png

2. 預設值使用可變物件(list/dict)

錯誤寫法:

def bad_append(item, target=[]):  #  所有呼叫都用同一個 list
    target.append(item)
    return target

print(bad_append(1))    # [1]
print(bad_append(2))    # [1, 2] ← 上次的結果還在!

正確寫法:

def good_append(item, target=None):
    if target is None:
        target = []     # 每次都建立新的 list
    target.append(item)
    return target

print(good_append(1))    # [1]
print(good_append(2))    # [2] ← 正確!

3. 回傳多值的處理

def calculate(a, b):
    return a + b, a - b, a * b    # 回傳 tuple

# 接收多個回傳值
add_result, sub_result, mul_result = calculate(10, 3)
print(f"加:{add_result}, 減:{sub_result}, 乘:{mul_result}")

超快速對照表

語法 意義
def 函式名(參數): 定義函式
return 值 傳出資料
函式名(引數) 呼叫函式
參數 = 預設值 預設參數值
*args 接收多個位置引數(tuple)
**kwargs 接收多個關鍵字引數(dict)

整合範例:自訂一個小工具函式庫

def add(x, y):
    """加法運算"""
    return x + y

def subtract(x, y):
    """減法運算"""
    return x - y

def multiply(x, y):
    """乘法運算"""
    return x * y

def divide(x, y=1):
    """除法運算,預設除以 1"""
    if y == 0:
        return "除以零錯誤"
    return x / y

def show_all(x, y):
    """展示所有運算結果"""
    print(f"加法:{add(x, y)}")
    print(f"減法:{subtract(x, y)}")
    print(f"乘法:{multiply(x, y)}")
    print(f"除法:{divide(x, y)}")

# 測試
show_all(10, 5)

變數作用域(Scope)補充

x = 100    # 全域變數

def test_scope():
    x = 50    # 區域變數,只在函式內有效
    print(f"函式內的 x:{x}")

test_scope()    # 輸出:函式內的 x:50
print(f"函式外的 x:{x}")    # 輸出:函式外的 x:100

Lambda 函式(一行式函式)

# 一般函式
def square(x):
    return x ** 2

# Lambda 函式(匿名函式)
square_lambda = lambda x: x ** 2

print(square(5))         # 25
print(square_lambda(5))  # 25

# 常用於排序、過濾
numbers = [3, 1, 4, 1, 5]
sorted_nums = sorted(numbers, key=lambda x: -x)  # 降序排列
print(sorted_nums)  # [5, 4, 3, 1, 1]

三題小練習

  1. 寫一個函式 greet(name):輸出 你好,{name}!
  2. 寫一個函式 even_or_odd(n):判斷奇偶,回傳 "偶數" 或 "奇數"
  3. 寫一個函式 calc(*nums):可接受任意數量數字,回傳 (總和, 平均)

練習題解答

# 題目 1
def greet(name):
    """打招呼函式"""
    print(f"你好,{name}!")

# 測試
greet("Jr")    # 輸出:你好,Jr!

# 題目 2
def even_or_odd(n):
    
    if n % 2 == 0:
        return "偶數"
    else:
        return "奇數"

# 測試
print(even_or_odd(4))    # 輸出:偶數
print(even_or_odd(7))    # 輸出:奇數

# 題目 3
def calc(*nums):
    """計算總和與平均
    
    參數:
        *nums: 任意數量的數字
        
    回傳:
        tuple: (總和, 平均)
    """
    if not nums:    # 如果沒有傳入數字
        return 0, 0
    
    total = sum(nums)
    average = total / len(nums)
    return total, average

# 測試
print(calc(1, 2, 3, 4, 5))    # 輸出:(15, 3.0)
print(calc(10, 20))           # 輸出:(30, 15.0)

進階技巧:錯誤處理

def safe_divide(x, y):
    """安全的除法運算
    
    參數:
        x (float): 被除數
        y (float): 除數
        
    回傳:
        float 或 str: 運算結果或錯誤訊息
    """
    try:
        if y == 0:
            raise ZeroDivisionError("不能除以零")
        return x / y
    except ZeroDivisionError as e:
        return f"錯誤:{e}"
    except Exception as e:
        return f"未知錯誤:{e}"

# 測試
print(safe_divide(10, 2))    # 5.0
print(safe_divide(10, 0))    # 錯誤:不能除以零

上一篇
Day 4:載入模組(import)
下一篇
# Day 6:物件導向 Part 1 (類別、物件、屬性、方法、self、__init__)
系列文
一塊一塊拼湊的 AI 樂高世界之旅8
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言