跳到主要內容

Day 7 函式基礎

Day 7 函式基礎

引言

到目前為止,我們寫的程式都是「一行一行往下執行」的直譯式結構。當同一段程式碼需要反覆出現,或是想把某個功能封裝起來重複使用時,這種寫法很快就會變得難以維護。函式(function)正是用來解決這個問題的工具,它讓我們可以把程式碼打包成可重複呼叫的單元。

這篇文章會帶你認識 Python 函式的基本概念,包括如何定義與呼叫函式、參數與回傳值的用法、預設參數與關鍵字參數的差異,以及如何為函式加上說明字串。學會函式後,你會發現程式碼可以寫得更短、更結構化,也更容易除錯。

定義與呼叫函式

在 Python 中,函式使用 def 關鍵字定義,後面接函式名稱、參數列與冒號,縮排內則是函式主體。定義好之後,必須「呼叫」函式才會真正執行。

def say_hello():
    print("Hello, world!")

# 呼叫函式
say_hello()  # 輸出 Hello, world!
say_hello()  # 再呼叫一次

第一行 def say_hello(): 是函式的定義,本質上只是告訴 Python「有個叫做 say_hello 的函式,內容是這樣」,並不會立即執行。要讓函式真的做事,必須寫 say_hello() 來呼叫它。每次呼叫,函式內的程式碼都會重新執行一次,這就是函式可以「重複使用」的基礎。

參數:把資料傳進函式

函式最棒的地方在於可以接收外部傳進來的資料,稱為參數(parameter)。呼叫函式時傳入的實際資料則稱為引數(argument)。有了參數,同一段函式就能處理不同的輸入,達到真正的重複利用。

def greet(name):
    print(f"Hello, {name}!")

greet("Alice")  # 輸出 Hello, Alice!
greet("Bob")    # 輸出 Hello, Bob!

這裡 name 是參數,在呼叫 greet("Alice") 時,「Alice」會被指定給 name,函式內就能用這個變數。函式可以定義多個參數,呼叫時依序傳入:

def add(a, b):
    print(a + b)

add(3, 5)  # 輸出 8

呼叫時傳入的引數數量必須與參數一致,否則會報 TypeError。這種「位置對應」的參數也稱為位置參數(positional argument)。

回傳值:把結果送回來

有些函式只是做事(例如 print()),但更多時候我們希望函式把計算結果「送回來」,這時候就要用 return 關鍵字。被 return 的值會成為函式的回傳值,呼叫端可以把它存進變數或繼續運算。

def add(a, b):
    return a + b

result = add(3, 5)
print(result)  # 輸出 8

# 也可以直接在 print 中呼叫
print(add(10, 20))  # 輸出 30

return 同時也會結束函式的執行,函式內 return 之後的程式碼不會被執行。如果函式內沒有寫 return,則會自動回傳 None。

def no_return():
    x = 1 + 1

print(no_return())  # 輸出 None

預設參數

有些參數在大部分情況下都會使用相同的值,這時可以給它一個預設值。呼叫函式時若沒有提供該參數,就會自動使用預設值;若提供了,則以提供的值為主。

def greet(name, greeting="Hello"):
    print(f"{greeting}, {name}!")

greet("Alice")             # 輸出 Hello, Alice!
greet("Bob", "Hi")         # 輸出 Hi, Bob!
greet("Carol", greeting="Hey")  # 用關鍵字參數指定,輸出 Hey, Carol!

上面的 greeting="Hello" 就是預設參數。注意在函式定義中,有預設值的參數必須放在沒有預設值的參數之後,否則會直接報語法錯誤。這是因為 Python 在解析呼叫端的引數時,是依序對應的。

關鍵字參數

當函式有很多參數時,呼叫端記住每個參數的位置很麻煩,這時候可以用「關鍵字參數」,明確指定每個值對應到哪個參數名稱。

def introduce(name, age, city):
    print(f"{name} 今年 {age} 歲,住在 {city}")

# 位置參數
introduce("Alice", 25, "Taipei")

# 關鍵字參數(順序可以不同)
introduce(city="Taipei", age=25, name="Alice")

兩種寫法的輸出完全相同。關鍵字參數讓程式碼更易讀,尤其當某些參數是布林值時,可讀性的差異更明顯(例如 savefig(filename, dpi=300, transparent=True))。位置參數與關鍵字參數也可以混用,但關鍵字參數必須寫在位置參數之後。

說明字串(docstring)

好的函式不只是能執行,還要讓別人(或未來的自己)看得懂。Python 慣例會在函式內第一行用三引號字串寫下「說明字串(docstring)」,說明函式的用途、參數與回傳值。

def celsius_to_fahrenheit(celsius):
    """將攝氏溫度轉換為華氏溫度。

    Args:
        celsius (float): 攝氏溫度。

    Returns:
        float: 對應的華氏溫度。
    """
    return celsius * 9 / 5 + 32

print(celsius_to_fahrenheit(25))  # 輸出 77.0
print(celsius_to_fahrenheit.__doc__)  # 顯示說明字串

說明字串可以用 help(函式名稱) 或 函式名稱.__doc__ 查看,是團隊協作與日後維護的重要工具。即使是自己寫的小工具,加上 docstring 也是一個好習慣。

函式的命名與撰寫慣例

Python 的函式命名遵循幾個簡單的慣例,掌握後能讓程式碼與社群一致,也更容易被其他開發者讀懂。

  • 使用小寫與底線:函式名稱使用蛇形命名(snake_case),例如 calculate_total 而不是 CalculateTotal。這是 Python 官方風格指南 PEP 8 的建議。
  • 動詞為主:因為函式代表「做一件事」,名稱通常以動詞開頭,例如 send_email、parse_config。回傳布林值的函式則常以 is_、has_ 開頭,例如 is_adult、has_permission。
  • 一個函式做一件事:盡量讓函式只負責單一功能,這樣更容易理解與測試。如果一個函式太長或做太多事,就應該考慮拆成幾個小函式。

舉個簡單的例子,下面的 is_even() 就是個命名良好的函式:

def is_even(number):
    """判斷 number 是否為偶數。"""
    return number % 2 == 0

print(is_even(4))  # True
print(is_even(7))  # False

變數的作用域

函式內定義的變數,預設只在函式內可見,這個範圍稱為「區域作用域(local scope)」。函式外看不到函式內的變數,反之亦然。這種設計避免了不同函式之間不小心互相干擾,是寫大型程式的重要基礎。

def add(a, b):
    total = a + b  # total 是區域變數
    return total

result = add(3, 5)
print(result)  # 輸出 8
# print(total)  # 這行會報 NameError,因為 total 不存在於全域

如果想在函式內讀取(或修改)函式外的全域變數,可以用 global 關鍵字宣告。不過多數情況下,更推薦的做法是「把值當參數傳進去、把結果用 return 傳出來」,而不是直接動全域變數,這樣程式碼會更容易追蹤與測試。

把函式組合成模組化程式

學會函式之後,我們可以把一個較大的問題拆成幾個小函式,每個函式負責一部分工作,最後再組合成完整的程式。舉例來說,計算一份成績報告,可以拆成「算平均」、「算最高分」、「算最低分」、「輸出報表」等小函式。

def average(scores):
    return sum(scores) / len(scores)

def top_score(scores):
    return max(scores)

def low_score(scores):
    return min(scores)

def report(name, scores):
    print(f"{name} 的成績報告")
    print(f"  平均:{average(scores):.1f}")
    print(f"  最高:{top_score(scores)}")
    print(f"  最低:{low_score(scores)}")

report("Alice", [85, 92, 78, 88])

這種「把大問題拆成小函式」的做法,不只讓程式碼更易讀,也方便日後維護與測試。例如當「平均的計算方式」要改成加權平均時,只需要修改 average() 一個函式,其他地方都不用動。這也是寫程式時非常重要的「單一職責原則」精神。

常見錯誤與小結

初學者寫函式時,有幾個常見的錯誤要特別注意:忘記 return、參數與引數數量不符、忘記冒號或縮排錯誤、把可變物件(串列、字典)當預設值等。養成「寫完函式先手動測試幾組輸入」的習慣,是避免這些錯誤的最好方法。

函式是把「會重複用到的邏輯」打包成可重複呼叫單元的核心工具。今天我們從最基本的 def 開始,一路學到參數、回傳值、預設值、關鍵字參數、說明字串與作用域。掌握這些之後,你已經具備寫出結構化、可維護程式碼的能力。

結語

今天我們認識了 Python 函式的基礎:使用 def 定義函式、用 () 呼叫函式、用參數接收輸入、用 return 回傳結果。我們也學會了預設參數、關鍵字參數、說明字串與變數作用域的概念。掌握函式之後,你已經能把重複的程式碼打包成可重複使用的單元,程式結構也會更清楚。

明天,我們會更進一步探討函式的進階主題,包括可以接收任意數量引數的 *args 與 **kwargs、更詳細的作用域規則、匿名函式 lambda,以及用遞迴解決問題的思路。

留言

這個網誌中的熱門文章

Day 2 變數與資料型別

Day 2 變數與資料型別 引言 寫程式的過程中,變數與資料型別是處理資料的基礎。變數是存放資料的容器,資料型別則決定這筆資料有哪些特性、可以進行哪些操作。學會定義變數、認識各種資料型別,是學好 Python 的關鍵一步。 這篇文章會帶你了解 Python 中變數的觀念、如何定義變數,以及常見的資料型別,包括整數、浮點數、字串、布林值,還有串列、元組、字典與集合等容器型別。我們也會介紹變數的命名規則與撰寫風格建議,以及如何用 type() 檢查資料型別。 什麼是變數?如何在 Python 中定義變數 變數是在程式執行時用來存放資料的名稱。透過定義變數,我們可以給一筆資料一個名字,並在程式的其他地方用這個名字取用該筆資料。在 Python 中,變數不需要事先宣告型別,因為 Python 是動態型別語言,變數的型別由指定給它的值決定。 定義變數的基本語法 在 Python 中定義變數非常簡單,只要用賦值符號 = 把值指定給變數即可。例如: x = 5 # 定義變數 x,並把整數 5 賦值給它 name = "Alice" # 定義變數 name,並把字串 "Alice" 賦值給它 在這裡,x 是一個變數,被賦予整數 5;name 是另一個變數,被賦予字串 "Alice"。 變數的更新與覆寫 變數的值可以修改,也就是說,我們可以在程式的不同地方給同一個變數新的值。例如: x = 10 # x 最初被賦予 10 x = 15 # x 的值現在被更新為 15 這樣就能依照需求,在程式執行過程中靈活調整變數的值。 Python 的動態型別系統 Python 和某些靜態型別語言不同,定義變數時不需要宣告型別。賦值時,Python 會根據值自動判斷變數的型別。例如: x = 5 # x 是整數 x = 3.14 # x 變成浮點數 x = "Hi" # x 變成字串 同一個變數在程式執行過程中可以存放不同型別的值,這是 Python 的彈性之一。 常見資料型別 在 Python 中,資料型別決定我們可以對變數進行哪些操作...

Day 1 Python 簡介與環境設定

Day 1 Python 簡介與環境設定 引言 在現在的科技環境裡,程式設計已經是一項重要技能。無論你是對資料科學有興趣、想成為開發者,或是想踏入人工智慧(AI)領域,學會寫程式都能明顯提升你的競爭力。在眾多程式語言中,Python 因為語法簡單、功能強大、應用範圍廣泛,成為許多人進入程式世界的第一選擇。這篇文章會帶你認識 Python 的背景與優勢,並一步步教你在不同系統上安裝與設定 Python 開發環境,最後寫出第一支 Python 程式。 為什麼選擇 Python? Python 是一種高階程式語言,由 Guido van Rossum 在 1991 年發布。Python 的設計哲學強調程式碼的可讀性,並用縮排來定義程式區塊,這點和許多使用大括號的語言不同。簡潔的語法讓它成為初學者的理想選擇;就算是經驗豐富的開發者,也能用它完成複雜的專案。 Python 的優勢如下: 簡單易學 :Python 的語法清楚、結構簡潔,初學者很快就能上手。和其他語言相比,學習曲線相對平緩,不需要先弄懂一堆複雜觀念,就能開始寫程式。 應用範圍廣泛 :從資料科學、網頁開發、人工智慧、機器學習、自動化測試到網路爬蟲,Python 都有大量開源函式庫與工具支援,而且在這些領域都扮演關鍵角色。 豐富的函式庫與框架 :Python 的函式庫生態系非常龐大。做資料分析有 NumPy、Pandas;開發網站有 Django、Flask;做深度學習有 TensorFlow、PyTorch。各種需求幾乎都能找到對應的套件,讓開發更有效率。 跨平台支援 :Python 支援 Windows、macOS、Linux 等作業系統,程式通常不需要太多修改就能跨平台執行,讓開發與部署更有彈性。 活躍的社群 :Python 擁有龐大的開發者社群。學習或開發上遇到問題,幾乎都能在社群與論壇(例如 Stack Overflow)找到答案,對初學者來說是很強的後盾,也能減少卡關時的挫折感。 Python 的應用領域 Python 的流行與強大功能,讓許多領域都開始大量使用它。以下是幾個常見的應用方向: 資料科學 :隨著大數據與人工智慧興起,資料科學大量使用 Python。NumPy、Pandas 與 Matplotlib 等工具能處理和分析龐...

Python 從入門到 PyTorch 深度學習:開啟 AI 世界的大門

Python 從入門到 PyTorch 深度學習:開啟 AI 世界的大門 隨著人工智慧(AI)與深度學習(Deep Learning)快速發展,越來越多人對這些技術產生興趣。不論你是想踏入 AI 領域的初學者,還是已經有程式基礎的開發者,學好 Python 與深度學習框架(例如 PyTorch),都能為你打開更多可能。 為什麼選擇 Python? Python 已經是資料科學與人工智慧領域的首選語言。它的語法簡潔、容易上手,而且擁有龐大的生態系與大量開源函式庫。無論是資料處理、資料視覺化,還是建立機器學習與深度學習模型,Python 都能勝任。對想進入 AI 或資料科學領域的人來說,它幾乎是必備工具。 PyTorch 是什麼? PyTorch 是由 Meta(原 Facebook)AI 研究團隊開發的開源深度學習框架,以易用、靈活和動態計算圖著稱,是許多 AI 研究人員與開發者的首選。相較於其他框架,PyTorch 的寫法更貼近原生 Python,對初學者相對友善。無論是簡單的實驗,還是複雜的深度學習模型,PyTorch 都能提供強大的支援。 這個系列能帶給你什麼? 這個系列會從 Python 的基礎開始,帶你一步一步學習,最後能自己用 PyTorch 建立深度學習模型。即使你完全沒有寫過程式,也能跟著文章的節奏累積技能,理解 AI 與深度學習的核心觀念。 本系列涵蓋的主題 Python 基礎:從變數、條件判斷到函式與模組。 資料處理工具:用 NumPy 與 Pandas 有效率地操作資料。 資料視覺化:用 Matplotlib 與 Seaborn 把資料畫成圖表。 深度學習的數學基礎:線性代數、微積分與機率。 PyTorch 入門:理解張量、模型建構與 GPU 加速。 基礎深度學習模型:CNN 與 RNN 的實作應用。 深度學習專案實戰:從資料前處理到模型部署的端到端流程。 誰適合這個系列? 程式初學者 :如果你對 AI 充滿好奇,卻還沒寫過程式,系列的第一部分會帶你快速上手 Python,並幫助你理解深度學習的基本觀念。 資料科學愛好者 :如果你已經熟悉一些資料處理方法,進階部分會教你如何用 PyTorch 建構深度學習模型。 開發者與研究人員 :想更深入了...