Home
Explore Uedu
Student Console
Register as Member/Login
Research Informed Consent Center
Survey Center
Educational Big Data Challenge
Claim or create a course
Try a Scenario Task
Support & Messages
Uptime Data

UeduGPTs

--

Jupyters

4

Local AI

--

Uedu Code

--

Taipei AQI 46 · Taichung AQI 76 · Tainan AQI 67 · Kaohsiung AQI 64
AI Reply Desktop Notifications

Show a desktop notification when the AI TA finishes replying

Chat Message Notifications

Notify me when classmates post messages in the forum

Sound notification

Play an alert sound whenever there is a new notification

Unit 14

函數的引數

位置、關鍵字、預設值與不定長度引數
Interaction實作 20 minute(s)

Learning Objectives

  • 位置引數(positional arguments):依順序對應參數
  • 關鍵字引數(keyword arguments):依名稱對應參數
  • 預設引數(default arguments):沒有提供時使用預設值
  • 不固定個數引數(arbitrary arguments):*args 與 **kwargs

四種傳引數的方法

上一課的函數,呼叫時要照順序給齊每個引數。實際寫程式時常會遇到:參數很多記不住順序、 大部分情況都用同一個值、或事先不知道會傳進幾個值。Python 提供四種傳引數的方法:

方法 定義時 呼叫時
位置引數(必要引數) def f(a, b): f(1, 2)
關鍵字引數 同上,不需要特別寫法 f(b=2, a=1)
預設引數 def f(a, b=10): f(1) 或 f(1, 5)
不固定個數引數 def f(*args, **kwargs): f(1, 2, 3, x=4)

用語提醒:定義函數時小括號裡的名稱叫參數(parameter),呼叫時實際傳進去的值叫引數(argument)。

位置引數與關鍵字引數

每次呼叫時,看右邊 printinfo 框架裡的 name 與 age 各拿到什麼值。第 6 行把順序放反了,程式不會出錯,但結果是錯的;第 7 行用關鍵字引數,就不必在意順序。

預設引數

dbname 與 port 有預設值,呼叫時可以省略。看第 7 行:想跳過中間的 dbname、只改 port,就用關鍵字引數。

錯誤的函數呼叫

定義預設引數時,預設引數必須放在位置引數之後:def f(a, b=1): 可以,def f(a=1, b): 是語法錯誤。

呼叫時常見的三種錯誤:

printinfo()                              # 少了必要引數 tblname
printinfo(port=8888, 'person')           # 關鍵字引數後面又接位置引數
printinfo('person', tblname='products')  # tblname 被給了兩次

第二種在程式還沒開始執行時就會被發現(SyntaxError),整支程式都不會跑; 另外兩種要到執行那一行時才引發 TypeError,可以用 try/except 接住,下面的範例就是這樣示範。

看 TypeError 的訊息

每個 try 區塊裡都是一次錯誤的呼叫。注意錯誤發生時函數內容完全沒有執行,訊息會清楚說明是哪個參數出了問題,養成讀錯誤訊息的習慣很有幫助。

想一想:位置、關鍵字與預設值

1.

下面的程式會印出什麼?

def area(length, width=1):
    return length * width

print(area(5), area(5, 3), area(width=2, length=4))
2.

已知 def area(length, width=1):,執行 area(width=15) 會發生什麼事?

3.

下列哪一種函數定義是不合法的?

第 1 次作答

不固定個數引數:*args

參數名稱前面加一個星號 *,就能接收任意個位置引數,它們會被收集成一個元組。看右邊 vartuple 的型態;沒有多出來的引數時,它是空元組 ()。

**kwargs:收集關鍵字引數

兩個星號 ** 會把多出來的關鍵字引數收集成字典,引數名稱變成 key。最後兩行是反方向的用法:呼叫時寫 * 把序列拆開、寫 ** 把字典拆開,再當作引數傳進去。

陷阱:可變的預設值

預設值是在執行 def 那一刻只建立一次的。如果預設值是串列,每次沒傳 box 的呼叫都會共用同一個串列。看右邊:第二次呼叫 add_item 時,box 指向的還是第一次那個串列。安全的寫法是預設值用 None。

追蹤 *args、**kwargs 與預設值

1.

下面的程式會印出什麼?

def f(a, *rest):
    print(a, len(rest), rest)

f(1, 2, 3)
2.

下面的程式會印出什麼?

def log(msg, history=[]):
    history.append(msg)
    return len(history)

log("a")
log("b")
print(log("c"))
第 1 次作答

實作:預設引數與 *args

完成兩個函數:greet(name, greeting='Hello') 印出像 Hello, Amy! 的問候;average(*nums) 傳回所有數字的平均,沒有傳入任何數字時傳回 0。

你的輸出
預期輸出

重點精華回顧

  • 位置引數(必要引數):依順序對應參數,個數與順序要和定義一致。
  • 關鍵字引數:呼叫時寫 參數名稱=值,不必在意順序;混用時位置引數要在前面。
  • 預設引數:def f(a, b=10):,沒提供時用預設值;預設引數必須定義在位置引數之後。
  • 少給必要引數、同一個參數給兩次、引數太多,都會引發 TypeError。
  • *args 把多出來的位置引數收集成元組;**kwargs 把多出來的關鍵字引數收集成字典。
  • 呼叫時 *序列、**字典 可以把資料拆開當引數傳入。
  • 預設值只在 def 時建立一次,不要用串列、字典這類可變物件當預設值,改用 None。
這一課完成了!
Next lesson:匿名函數與變數可見度
你目前沒有登入,學習進度只存在這個瀏覽器。 Login 後,進度會跟著帳號,換電腦也看得到。