Python 函數入門:參數、返回值與進階技巧
函數 (function) 是一個非常核心的概念,如果你需要重複執行某一段相同的程式碼,不斷複製貼上會讓你的程式變得冗長且難以維護。函數能重複執行的問題,它把一組程式碼封裝起來,給它一個名字,之後可以透過這個名字來重複使用這段程式碼。這篇文章將帶你了解 Python 中的 function。
🧩 函數的基本結構
Python 中定義函數非常簡單,主要使用 def
關鍵字。 一個基本的函數結構包含:
def
關鍵字:告訴 Python 你要定義一個函數。- 函數名稱 (Function Name):你自己取的名稱,用來識別和呼叫函數。習慣上使用小寫字母和底線 (snake_case),例如
my_function
。 - 括號
()
:緊跟在函數名稱後面,裡面可以放參數 (parameters)。 - 冒號
:
:表示函數定義的開始。 - 縮排的程式碼區塊 (Indented Code Block):這就是函數的主體 (function body),也就是函數要執行的動作。
- (選擇性) 文件字串 (Docstring):用三個引號
"""docstring"""
包起來的字串,用來說明函數的功能、參數和返回值。
def greet():
"""這是一個簡單的打招呼函數。"""
print("Hello, Python!")
# 呼叫函數
greet()
在這個例子中,greet
就是函數名稱。當你執行 greet()
時,它就會印出 "Hello, Python!"。
📥 參數與引數 (Parameters and Arguments)
很多時候,函數需要一些外部的資料才能完成工作。這時候就需要用到參數和引數。
- 參數 (Parameters):在定義函數時,放在括號
()
裡面的變數名稱。它們像是函數內部的佔位符。 - 引數 (Arguments):在呼叫函數時,傳遞給函數的實際值。
def greet_user(name): # 'name' 是一個參數
"""根據提供的名字打招呼。"""
print(f"你好, {name}!")
greet_user("小明") # "小明" 是一個引數
greet_user("小華") # "小華" 是另一個引數
位置引數 (Positional Arguments)
引數會按照順序對應到參數。
def describe_pet(animal_type, pet_name):
"""顯示寵物的資訊。"""
print(f"我有一隻 {animal_type}。")
print(f"我的 {animal_type} 叫做 {pet_name.title()}。")
describe_pet("倉鼠", "毛毛")
關鍵字引數 (Keyword Arguments)
你可以明確指定引數要對應到哪個參數,這樣就不用擔心順序問題。
describe_pet(animal_type="貓咪", pet_name="花花")
describe_pet(pet_name="皮蛋", animal_type="狗狗") # 順序可以調換
預設參數值 (Default Parameter Values)
你可以為參數設定預設值。如果在呼叫函數時沒有提供該參數的引數,就會使用預設值。
def greet_default(name="訪客"): # 'name' 有預設值 "訪客"
print(f"你好, {name}!")
greet_default("小陳") # 輸出: 你好, 小陳!
greet_default() # 輸出: 你好, 訪客!
📤 函數的返回值 Return Values
函數不僅可以執行動作,還可以回傳結果給呼叫它的地方。這是透過 return
關鍵字來實現的。
返回 None
如果函數沒有明確的 return
語句,或者 return
後面沒有接任何值,它會自動返回一個特殊的值 None
。None
在 Python 中表示「沒有值」或「空值」。當然,你也可以自行返回 None
。
def print_sum(a, b):
result = a + b
print(f"總和是: {result}") # 這個函數只印出結果,沒有返回值
sum_value = print_sum(5, 3)
print(f"函數返回值: {sum_value}") # 輸出: 函數返回值: None
返回單個值
使用 return
關鍵字可以讓函數回傳一個計算結果或特定的值。
def add_numbers(x, y):
"""回傳兩個數字的總和。"""
return x + y
result = add_numbers(10, 5)
print(f"10 + 5 的結果是: {result}") # 輸出: 10 + 5 的結果是: 15
一旦執行到 return
語句,函數就會立即終止並回傳值。
返回多個值
Python 函數可以方便地一次返回多個值。實際上,Python 會將這些值打包成一個元組 (tuple) 返回。
def get_name_and_age():
name = "Paul"
age = 20
return name, age # 返回一個元組 ('Paul', 20)
# 可以用多個變數來接收返回的多個值
user_name, user_age = get_name_and_age()
print(f"姓名: {user_name}, 年齡: {user_age}") # 輸出: 姓名: Paul, 年齡: 20
# 或者直接接收整個元組
info = get_name_and_age()
print(f"資料: {info}") # 輸出: 資訊: ('Paul', 20)
print(f"元組 (tuple) 的第一個元素: {info[0]}") # 輸出: 元組 (tuple) 的第一個元素: Paul
🎁 函數作為物件 Functions as Objects
在 Python 中,函數是「一等公民 (first-class citizens)」。這代表函數和其他資料類型 (例如數字、字串、列表) 一樣,擁有同等的地位。你可以:
- 將函數賦值給變數。
- 將函數作為引數傳遞給其他函數。
- 讓函數作為另一個函數的返回值 (這個比較進階,這裡先不詳述)。
def say_hello():
return "Hello!"
# 1. 將函數賦值給變數
greet_message_func = say_hello
print(greet_message_func()) # 輸出: Hello!
# 2. 將函數作為引數傳遞給其他函數
def execute_function(func_to_run):
print("準備執行函數...")
result = func_to_run()
print(f"函數執行結果: {result}")
execute_function(say_hello)
# 輸出:
# 準備執行函數...
# 函數執行結果: Hello!
def add(a, b):
return a + b
def subtract(a, b):
return a - b
def calculate(operation_func, x, y):
return operation_func(x, y)
result_add = calculate(add, 10, 3)
result_subtract = calculate(subtract, 10, 3)
print(f"10 + 3 = {result_add}") # 輸出: 10 + 3 = 13
print(f"10 - 3 = {result_subtract}") # 輸出: 10 - 3 = 7
這種特性讓 Python 的函數非常靈活,是許多進階編程技巧 (如裝飾器 Decorators) 的基礎。
🪆 嵌套函數 Nested Functions
Python 允許你在一個函數內部定義另一個函數,這就是所謂的嵌套函數或內部函數 (inner function)。 內部函數只能在其外部函數 (outer function) 的作用域內被存取和呼叫。內部函數可以存取外部函數的變數。
def outer_function(text):
message = text # 外部函數的變數
def inner_function():
# 內部函數可以存取外部函數的 'message' 變數
print(f"內部訊息: {message.upper()}")
print("準備從外部函數呼叫內部函數...")
inner_function() # 在外部函數中呼叫內部函數
outer_function("hello world")
# 輸出:
# 準備從外部函數呼叫內部函數...
# 內部訊息: HELLO WORLD
這對於封裝輔助功能、實現閉包 (closures) 和裝飾器等都很有用。
💡 型別提示 Type Hints
Python 是一種動態型別語言,這代表你在定義變數或函數參數時,不需要事先聲明它們的型別。Python 直譯器會在執行時期自動推斷型別。 然而,從 Python 3.5 開始,引入了型別提示 (Type Hints) 的功能。它允許你為函數參數和返回值「建議」型別。
型別提示的語法:
- 參數型別提示:
parameter_name: type
- 返回值型別提示:
def function_name(...) -> return_type:
def greet_typed(name: str) -> str:
return f"Hello, {name}"
def add_typed(a: int, b: int) -> int:
return a + b
greeting = greet_typed("Python 開發者")
sum_result = add_typed(5, 10)
print(greeting) # 輸出: Hello, Python 開發者
print(sum_result) # 輸出: 15
型別提示的好處:
- 提升程式碼可讀性:其他人 (或未來的你) 可以更容易理解函數期望接收什麼型 welchen 的資料,以及它會回傳什麼型 welchen 的資料。
- 編輯器支援:現代的程式碼編輯器 (如 VS Code, PyCharm) 可以利用型別提示來提供更好的自動完成 (autocomplete) 功能和即時的型別檢查。如果傳遞了不符合提示的型別,編輯器通常會顯示警告。
- 提早發現潛在錯誤:雖然 Python 在執行時期不會因為型別不符提示而阻止程式運行 (除非操作本身不合法),但編輯器的警告可以幫助你在開發階段就注意到可能的型別錯誤,從而提早修正。
重要提醒:
- 型別提示是完全選擇性的 (optional)。你可以選擇用,也可以選擇不用。
- Python 執行時期不會強制執行型別提示。即使你傳遞了與提示不符的型別的引數,只要程式碼在邏輯上可以執行,它仍然會運行。型別提示主要用於靜態分析工具和開發者之間的溝通。python型別提示就像是給程式碼加了註解,告訴編輯器和其他開發者你的意圖。如果你堅持傳遞錯誤的型別,程式碼仍然會嘗試執行,只是編輯器可能會提醒你「這樣做可能不是個好主意」。
def process_data(data: list) -> None: # 假設這裡期望 data 是一個列表 if isinstance(data, list): # 實際運行時的檢查還是需要的 for item in data: print(item) else: print(f"警告: 傳入的 data (值: {data}) 並非列表型別!") process_data([1, 2, 3]) # 正常運作 process_data("這不是列表") # 執行時期會印出警告,但不會因為型別提示而直接報錯 # 編輯器層面可能會在你寫 process_data("...") 時就給出警告
✍️ Lambda 函數簡介
Lambda 函數是一種小型的、匿名的、單行表達式的函數。它們使用 lambda
關鍵字定義,而不是 def
。 Lambda 函數的語法是:lambda arguments: expression
它們通常用在需要一個簡單函數,但又不想另外用 def
定義一個完整函數的場合。
# 一個簡單的加法 lambda 函數
add_lambda = lambda x, y: x + y
result = add_lambda(5, 3)
print(f"Lambda 加法結果: {result}") # 輸出: Lambda 加法結果: 8
# Lambda 常用於排序的 key
points = [(1, 2), (3, 1), (5, -4), (0, 0)]
# 根據每個元組的第二個元素排序
points.sort(key=lambda point: point[1])
print(f"排序後的點: {points}") # 輸出: 排序後的點: [(5, -4), (0, 0), (3, 1), (1, 2)]
Lambda 函數功能有限,它只能包含一個表達式,不能有多行語句。對於初學者來說,了解它們的存在即可,更複雜的函數還是建議使用 def
來定義,以保持程式碼的清晰度。
📝 總結
函數是 Python 編程中不可或缺的工具。透過定義和使用函數,你可以:
- 組織程式碼,使其更具結構化和模組化。
- 重複使用程式碼,避免不必要的複製貼上。
- 提高程式碼的可讀性和可維護性。
本文介紹了函數的基本定義、參數與引數的傳遞、不同類型的返回值、函數作為物件的特性、嵌套函數的概念,以及方便的型別提示和簡潔的 Lambda 函數。掌握這些基礎知識,將為你學習更進階的 Python 編程技巧打下堅實的基礎。多練習編寫和使用函數,你會發現它們的強大之處!