
學完Python的基礎課程後,大家對於Python已經有了一定程度的了解,可以開始踏入Python進階的課程了! 這邊將介紹 Python 中的函數、模組與套件,這些技巧可以提升結構化、模組化程式的能力,讓程式碼更易於維護、重用與共享。
✍️ 函數(Function)
函數是一組具有特定功能的代碼片段,使用函數可以避免重複代碼,提高程式的可讀性與可重用性。
基礎語法
def 函數名稱(參數1, 參數2, ...):
"""函數的說明文件字串 (選填)"""
# 函數邏輯
return 結果 (選填)
基礎函數
def greet():
print("Hello, Python!")
# 呼叫函數
greet()
# 輸出
Hello, Python!
帶參數和返回值
# 定義函數
def add_numbers(a, b):
return a + b
# 呼叫函數
result = add_numbers(10, 5)
print(f"The result of addition is: {result}")
# 輸出
The result of addition is: 15
函數的參數
- 位置參數:按順序傳遞值。
- 關鍵字參數:指定參數名稱來傳遞值。
- 預設參數:為參數設定預設值。
- 可變參數:接受不定數量的參數。
def introduce(name, age=18, *hobbies):
print(f"My name is {name} and I am {age} years old.")
if hobbies:
print(f"My hobbies are: {', '.join(hobbies)}")
introduce("Alice", 25, "reading", "traveling", "coding")
introduce("Bob")
# 輸出
My name is Alice and I am 25 years old.
My hobbies are: reading, traveling, coding
My name is Bob and I am 18 years old.
高階函數
高階函數是以函數作為參數或返回值的函數。Python 提供了多種高階函數,例如 map 與 apply,結合 匿名函數 lambda 可以實現清晰且高效的數據處理功能。
lambda
- lambda 是 Python 提供的匿名函數語法,用於創建臨時函數。
- 語法:
lambda 参数: 表達式
- 特點:
- 只能寫單行表達式。
- 沒有函數名稱,通常用於簡單邏輯。
def add(x, y):
return x + y
# 使用 lambda 替換
add_lambda = lambda x, y: x + y
print(add(5, 3)) # 8
print(add_lambda(5, 3)) # 8
map
- map(func, iterable) 是一個內建高階函數,將 func 函數應用到 iterable 的每個元素,並返回一個 迭代器
- 不會直接返回列表,而是返回一個映射對象,需要用 list() 或 for 轉換。
- 適合處理數據的批量轉換。
- 在Pandas中適用於Series資料格式的處理(單列/單欄)
numbers = [1, 2, 3, 4]
result = map(lambda x: x ** 2, numbers)
print(list(result)) # [1, 4, 9, 16]
apply
- apply 是 Pandas 中的一個方法,用於將函數應用到資料框的列或行
- 用於 Pandas 列 (Series) 或 整張表格 (DataFrame) 的批量數據處理。
- 適合處理更複雜的數據轉換場景。
import pandas as pd
# 建立數據框
data = {"Name": ["Alice", "Bob", "Charlie"],
"Age": [25, 30, 35],
"Salary": [50000, 60000, 70000]}
df = pd.DataFrame(data)
# 將年齡提升 10%
df["Age * 1.1"] = df["Age"].apply(lambda x: x * 1.1)
print(df)
# 輸出
Name Age Salary Age * 1.1
0 Alice 25 50000 27.5
1 Bob 30 60000 33.0
2 Charlie 35 70000 38.5
函數作為參數
def apply_function(data, func):
return [func(x) for x in data]
# 測試
numbers = [1, 2, 3, 4]
squared = apply_function(numbers, lambda x: x ** 2)
print(squared)
# 輸出
[1, 4, 9, 16]
比較

遞迴函數
遞迴函數是一個函數直接或間接地調用其自身,常用於解決樹結構、階層關係或數列問題。其運算邏輯與效率常常與for迴圈做比較,屬於演算法中的一種。
優點:
- 直觀且數學風格:遞迴函數與階層的數學定義非常接近,公式簡單明瞭。
- 簡潔性:在許多情況下,對遞迴算法的理解更直觀,代碼量少。
缺點:
- 計算效率:遞迴每一次呼叫都需要佔用額外的函數記憶體空間,對於較大的數值(如 100!)可能會導致記憶體不足或觸發 RecursionError。
- 限制:Python 遞迴的深度有限(默認為約 1000 層),如果數字 n 太大,會因為超出遞迴深度限制而失敗。
# 遞迴版本
def factorial(n):
if n == 0: # 基底條件
return 1
else:
return n * factorial(n - 1) # 遞迴條件
# for迴圈版本
def factorial(n):
result = 1 # 初始值設為 1,因為 0! = 1
for i in range(1, n + 1): # 從 1 到 n(含 n)
result *= i # 將 i 乘入結果中
return result
# 測試
print(factorial(5)) # 120

📦 模組(Module)
- 模組是包含 Python 代碼(如函數和類別)的一個檔案,模組的作用是實現代碼邏輯的組織化和重用。
- 程式碼必須以函數的方式撰寫並以.py格式儲存才會是模組
- 每個 .py 檔案都是一個模組,可以被其他程式 import 來使用。
建立模組
# my_module.py
def add(a, b):
return a + b
def subtract(a, b):
return a - b
導入模組
# main.py
import my_module # 導入模組
# 使用模組內的函數
result1 = my_module.add(10, 5)
result2 = my_module.subtract(10, 5)
print(f"Addition: {result1}")
print(f"Subtraction: {result2}")
# 輸出
Addition: 15
Subtraction: 5
使用別名
import my_module as mm
result = mm.add(3, 2)
print(f"Result: {result}")
# 輸出
Result: 5
導入特定函數
# 從模組中只導入特定函數
from my_module import add
result = add(7, 3)
print(f"Result: {result}")
# 輸出
Result: 10
__name__
== "__main__"
的作用
- 能讓模組既可以被其他模組導入,也可以作為主程式單獨執行
- 在開發過程中,添加
if __name__ == "__main__":
是一種良好的開發習慣,即便模組最初不需要獨立執行,將來需求可能也會改變。 - 添加該結構有助於分離模組內的功能定義和測試邏輯,提高代碼的可維護性和重用性。
__name__
是什麼?
在 Python 中,name 是一個內建變數,代表當前模組的名稱:
- 如果 Python 腳本是被直接執行,name 的值會是 "main"。
- 如果 Python 腳本是被匯入(import)到其他腳本中執行,name 的值會是該模組的名稱(例如模組檔案的名稱:module_name)
if __name__ == "__main__"
: 判斷的邏輯
- 當腳本作為主程序運行時,Python 會將 name 設定為 "main",這時條件為真,會執行在 if 內的代碼
- 當腳本被作為模組匯入到其他腳本中時,name 不等於 "main",這時條件為假,if 內的代碼不會被執行
# my_module.py
def add(a, b):
return a + b
if __name__ == "__main__":
print("This module is run directly!")
# 輸出
This module is run directly!
📂 套件(Package)
- 套件是包含多個模組的資料夾,用於組織和管理大型程式
- 資料夾必須包含一個特殊的 __init__.py 文件,來聲明該資料夾是套件
套件結構
my_package/
__init__.py # 用於初始化模組
math_utils.py
string_utils.py
建立套件
# math_utils.py
def add(a, b):
return a + b
def multiply(a, b):
return a * b
# string_utils.py
def uppercase(text):
return text.upper()
def lowercase(text):
return text.lower()
# main.py
from my_package.math_utils import add, multiply
from my_package.string_utils import uppercase
result1 = add(5, 3)
result2 = multiply(4, 2)
result3 = uppercase("hello")
print(f"Addition: {result1}")
print(f"Multiplication: {result2}")
print(f"Uppercase: {result3}")
# 輸出
Addition: 8
Multiplication: 8
Uppercase: HELLO
🔤類型提示(Typing Hint)
Python 是一門 動態類型語言,變數的類型在執行時被解釋器檢測,並未在代碼中強制要求指定類型。然而,隨著大型專案的規模擴大,程式的可讀性和可維護性可能因為缺乏清晰的類型而變低。
Typing Hint (類型提示) 是 Python 提供的一種工具,用於在程式碼中指示變數、函數參數和返回值的類型。這是一種可選的靜態類型檢查工具,有助於提升程式的 清晰度 和 可維護性,同時為開發人員提供更好的編譯器支援與除錯提示。
- 不影響程式執行:類型提示不會改變 Python 程式的行為,僅作為開發協助工具。
- 提升可讀性與協作性:類型提示能讓代碼的意圖更明確,對於團隊合作與大型專案非常有效。
- 支援 IDE 和檢測工具:現代 IDE(如 PyCharm、VSCode 等)和工具(如 mypy)能根據類型提示檢測靜態類型錯誤。
- 靈活性:支援基本類型(如 int、str)、容器類型(如 List、Dict)以及自定義的複合類型。
基本語法
age: int = 25 # age 是整數型別
name: str = "Alice" # name 是字串型別
is_active: bool = True # is_active 是布林型別
在函數中定義型別
def greet(name: str) -> str:
return f"Hello, {name}!"
# 使用 typing hint 函數
message = greet("Alice")
print(message) # Hello, Alice!
常見類型提示

from typing import List
def sum_list(numbers: List[int]) -> int:
return sum(numbers)
result = sum_list([1, 2, 3, 4])
print(result) # 10
💡除了以上基本的型別之外,還可以使用Pillow中的Image和numpy.ndarray等特殊或是其他自定義的型別作為提示之用。
🔍特殊參數: *args
/ **kargs
在 Python 中,函數的參數有幾種類型,包括 位置參數、關鍵字參數 和兩種特殊參數 *args
與 **kwargs
。 *args
和 **kwargs
為函數提供了靈活的參數接收方式,可以處理任意數量的 位置參數 和 關鍵字參數。
*args
:可變位置參數
- 當函數不知道會接收多少個位置參數時,可以使用
*args
作為參數。 - 在函數內,
*args
會將所有 位置參數 打包成一個 元組 (tuple)。 *args
是 Python 中的慣例命名,也可以使用其他名稱,只需在參數前加*
,例如:*numbers
。
def add_numbers(*args):
return sum(args)
result = add_numbers(1, 2, 3, 4, 5)
print(f"The sum is: {result}")
# 輸出
The sum is: 15
**kwargs
:可變關鍵字參數
- 當函數想接收任意數量的 關鍵字參數(key=value 格式) 時,可以使用
**kwargs
。 - 在函數內,
**kwargs
會將所有關鍵字參數打包成一個 字典 (dictionary)。 **kwargs
是 Python 中的慣例命名,也可以使用其他名稱,只需在參數前加**
,例如:**data
。
def build_profile(**kwargs):
return kwargs
profile = build_profile(name="Alice", age=25, profession="Developer")
print(profile)
# 輸出
{'name': 'Alice', 'age': 25, 'profession': 'Developer'}
*args
和 **kwargs
的混合使用
可以在同一個函數中同時使用 *args
和 **kwargs
,這樣就可以同時接收不定數量的 位置參數 和 關鍵字參數。
參數的順序必須為:
- 位置參數(普通參數)
*args
**kwargs
def example_function(a, b, *args, **kwargs):
print(f"普通參數 a: {a}, b: {b}")
print(f"*args: {args}")
print(f"**kwargs: {kwargs}")
example_function(
10,
20,
30, 40, 50, # 傳遞位置參數
name="Alice", age=25 # 傳遞關鍵字參數
)
# 輸出
普通參數 a: 10, b: 20
*args: (30, 40, 50)
**kwargs: {'name': 'Alice', 'age': 25}
進階符號用法
可用於設計需要高度動態性的函數,例如 Web 框架的路由定義或 API 請求參數處理。
def greet(name, age):
print(f"My name is {name} and I am {age} years old.")
info = ("Alice", 25) # 位置參數
greet(*info) # 解包為位置參數
detail = {"name": "Bob", "age": 30} # 關鍵字參數
greet(**detail) # 解包為關鍵字值
# 輸出
My name is Alice and I am 25 years old.
My name is Bob and I am 30 years old.
比較
