Python 中的函數參數
在通常情況下,定義函數時,函數的參數個數是預先確定的。例如,編寫計算兩個數相加的函數 add(a, b),代碼如下:
def add(a, b):
return a + b
sum = add(1, 2)
- 在第 1 行,定義了函數 add,函數有兩個參數,第 1 個參數是 a,第 2 個參數是 b
- 在第 2 行,計算參數 a 和 參數 b 的累加和,通過 return 語句將計算結果返回給調用者
- 在第 4 行,通過 add(1, 2) 調用函數 add
- 將整數 1 傳遞給第 1 個參數 a
- 將整數 2 傳遞給第 2 個參數 b
傳入的兩個整數按照位置順序依次賦給函數的參數 a 和 b,參數 a 和參數 b 被稱為位置參數。
在 Python 中,調用函數時,根據函數定義的參數位置來傳遞參數,要求傳遞的參數與函數定義的參數兩者一一對應,如果 “傳遞的參數個數” 不等于 “函數定義的參數個數”,運行時會報錯,例如:
def add(a, b):
return a + b
sum = add(1, 2, 3)
- 在第 1 行,定義了函數 add,函數有 2 個參數
- 在第 4 行,通過 add(1, 2, 3) 調用函數 add,傳遞了 3 個參數
因為 “傳遞的參數個數” 不等于 “函數定義的參數個數”,運行時報錯如下:
C:\> python add.py
Traceback (most recent call last):
File "error.py", line 4, in <module>
sum = add(1, 2, 3)
TypeError: add() takes 2 positional arguments but 3 were given
在第 5 行,運行時提示:函數 add 有 2 個位置參數,但是調用時傳遞了 3 個位置參數。
1. 位置參數實例
1.1 函數沒有任何位置參數
程序運行輸出如下:
hello
world
1.2 函數有 1 個位置參數
def hello_world(n):
for i in range(n):
print('hello world')
hello_world(3)
程序運行輸出如下:
hello world
hello world
hello world
1.3 函數有 2 個位置參數
def hello_world(n, string):
for i in range(n):
print(string)
hello_world(n, 'HELLO WORLD')
程序運行輸出如下:
HELLO WORLD
HELLO WORLD
HELLO WORLD
2. 默認參數
2.1 概述
調用函數時,“傳遞的參數” 需要與 “函數定義的參數” 一一對應,例如:
def add_student(name, age, city):
print(name)
print(age)
print(city)
add_student('tom', 10, 'nanjing')
- 在第 1 行,定義函數 add_student,函數定義了 3 個參數
- 在第 5 行,調用函數 add_student,傳遞了 3 個參數
程序正常運行,輸出結果如下:
tom
10
nanjing
如果 “傳遞的參數個數” 少于 “函數定義的參數個數”,程序會報錯,例如:
def add_student(name, age, city):
print(name)
print(age)
print(city)
add_student('jerry', 12)
- 在第 1 行,定義函數 add_student,函數定義了 3 個參數
- 在第 5 行,調用函數 add_student,傳遞了 2 個參數
程序運行時,報錯如下:
Traceback (most recent call last):
File "add_student.py", line 5, in <module>
add_student('jerry', 12)
TypeError: enroll() missing 1 required positional argument: 'city'
在定義函數時,可以為參數提供一個缺省值,如果傳遞參數時,可以忽略部分參數,舉例如下:
def add_student(name, age, city = 'nanjing'):
print(name)
print(age)
print(city)
add_student('jerry', 12)
- 在第 1 行,定義函數 add_student,函數定義了 3 個參數
- 參數 name 和參數 age 是位置參數
- 參數 city 是缺省參數,該參數的缺省值是 'nanjing’
- 在第 5 行,調用函數 add_student,傳遞了 2 個參數
- 參數 name 被設定為 ‘jerry’
- 參數 age 被設定為 12
- 調用函數時沒有傳遞參數給 city,因此參數 city 被設定為缺省值 ‘nanjing’
程序正常運行,輸出結果如下:
tom
10
nanjing
2.2 簡化函數調用
現在需要多次調用 add_student 對一批學生進行處理,可以使用如下代碼:
def add_student(name, age, city):
print(name)
print(age)
print(city)
add_student('tom', 10, 'nanjing')
add_student('jerry', 12, 'nanjing')
add_student('mike', 12, 'nanjing')
add_student('john', 11, 'nanjing')
add_student('jobs', 13, 'beijing')
- 在第 6 行到第 10 行,新增 5 個學生 tom、jerry、mike、john、jobs
- 大部分學生來自于相同的城市,極個別學生來自于外地城市
使用默認參數,可以簡化函數的調用,尤其是在函數需要被頻繁調用的情況下。因為大部分學生來自于 nanjing,可以為參數 city 設定一個默認值 nanjing,如下所示:
def add_student(name, age, city="nanjing"):
print(name)
print(age)
print(city)
add_student('tom', 10)
add_student('jerry', 12)
add_student('mike', 12)
add_student('john', 11)
add_student('jobs', 13, 'beijing')
- 在第 6 行到第 10 行,新增 4 個學生 tom、jerry、mike、john,這 4 個學生來自于相同的城市 ‘nanjing’,調用函數 add_student 時不需要的傳遞參數 ‘nanjing’
- 在第 10 行,新增 1 個學生 jobs,該學生來自于 beijing,調用函數 add_student 時需要的傳遞參數 ‘beijing’
3. 可變參數
3.1 概述
假設需要編寫一個函數 add,函數 add 計算 2 個數的累加和,代碼如下:
編寫計算 3 個數的累加和函數,代碼如下:
如果需要編寫計算 4 個數的累加和函數,可以用上述方式再增加一個函數,顯然,這樣的方法是繁瑣的。我們的需求是:編寫一個計算累加和的函數 add,但是函數 add 的參數個數是預先不確定的。
Python 提供了一種可變參數機制用于解決這樣的問題,在函數定義中,可以將函數設定為可以接受任意數量的參數,函數調用時就可以傳遞任意數量的參數。
在函數定義中,在參數前加上符號 * 表示函數可以接受可變數量的參數,如下所示:
def 函數(*args):
函數體
- 該函數被設定為能夠接受可變數量的參數
- args 的類型是元組
- 調用該函數時,所有的參數被合并成一個元組
- 合并后的元組被賦值給 args,通過遍歷 args 可以訪問傳遞的參數
3.2 例子
使用可變參數重新實現計算累加和的函數 add,函數 add 能夠接受任意個數的參數,代碼如下:
def add(*args):
sum = 0
for arg in args:
sum = sum + arg
print('len = %d, sum = %d' % (len(args), sum))
add(1)
add(1, 2)
add(1, 2, 3)
- 在第 1 行,定義函數 add,args 是可變參數,args 的類型是一個元組
- 在第 2 行,設定累加和 sum 的初值為 0
- 在第 3 行,調用函數 add 時,所有的參數被合并成一個元組賦值給 args,因此使用 for 循環遍歷元組 args,相當于遍歷所有的輸入參數
- 在第 4 行,變量 arg 表示當前遍歷的參數,將其加入到變量 sum 中
- 在第 5 行,打印 args 的長度和計算結果 sum
- 在第 7 行,傳遞 1 個參數給 add
- 在第 8 行,傳遞 2 個參數給 add
- 在第 9 行,傳遞 3 個參數給 add
程序運行時,輸出如下:
len = 1, sum = 1
len = 2, sum = 3
len = 3, sum = 6
4. 關鍵字參數
4.1 概述
通常情況下,調用函數時,以直接給出參數值的形式傳遞參數,如下所示:
def add(a, b):
return a + b
add(1, 2)
- 在第 3 行,整數 1 和整數 2 作為參數值傳遞給參數 a 和 參數 b
Python 允許調用函數時,以 “參數名 = 參數值” 的形式傳遞參數,如下所示:
def add(a, b):
return a + b
add(a = 1, b = 2)
"參數名 = 參數值" 形式的參數,例如 a = 1 和 b = 2,被稱為關鍵字參數。在函數定義中,在參數前加上符號 ** 參數表示函數可以接收關鍵字參數,如下所示:
def 函數(**kw_args):
函數體
- 該函數被設定為能夠接收關鍵字參數
- kw_args 的類型是字典
- 調用該函數時,所有的關鍵字參數被合并成一個字典
- 合并后的字典被賦值給 kw_args,通過訪問 kw_args 可以訪問參數名和參數值
4.2 例子
假設需要通過兩種方式來創建一個人的姓名:
-
直接給出人的姓名,需要一個參數:full_name
- 例子,如果 full_name 等于 ‘ZhangSan’,則用這種方式創建的姓名是 ‘ZhangSan’
-
分別給出人的姓和名,需要兩個參數: first_name 和 last_name
- 參數 first_name 表示姓
- 參數 last_name 表示名
- 例子,如果 first_name 等于 ‘Zhang’、last_name 等于 ‘San’,則用這種方式創建的姓名是 ‘ZhangSan’
現在使用 Python 的關鍵字參數機制完成函數 create_full_name,代碼如下:
def create_full_name(**kw_args):
if 'full_name' in kw_args:
full_name = kw_args['full_name']
return full_name
if 'first_name' in kw_args and 'last_name' in kw_args:
first_name = kw_args['first_name']
last_name = kw_args['last_name']
full_name = first_name + last_name
return full_name
print(create_full_name(full_name = 'ZhangSan'))
print(create_full_name(first_name = 'Li', last_name = 'Si'))
運行程序,輸出結果如下:
ZhangSan
LiSi
- 在第 1 行,創建函數 create_full_name,該函數能夠接受關鍵字參數
- 該函數被調用時,所有關鍵字參數被合并成一個字典,被賦值給參數 kw_args
- kw_args 的類型是字典,它包含了所有的關鍵字參數
- 在第 2 行,檢查 kw_args 中是否包含參數 full_name
- 在第 3 行,從 kw_args 中獲取參數 full_name 的值
- 在第 4 行,返回 full_name
- 在第 6 行,檢查 kw_args 中是否包含參數 first_name 和 last_name
- 在第 7 行,從 kw_args 中獲取參數 first_name 的值
- 在第 8 行,從 kw_args 中獲取參數 last_name 的值
- 在第 9 行,根據 first_name 和 last_name 計算 full_name
- 在第 10 行,返回 full_name
- 在第 13 行,通過 “直接給出人的姓名” 的方式調用 create_full_name
- 傳遞關鍵字參數 full_name = ‘ZhangSan’
- 關鍵字參數被合并入一個字典 kw_args
- 字典 kw_args 中包含一條鍵值對
- 在第 13 行,通過 “分別給出人的姓和名” 的方式調用 create_full_name
- 傳遞關鍵字參數 first_name = ‘Li’、last_name = ‘Si’
- 關鍵字參數被合并入一個字典 kw_args
- 字典 kw_args 中包含兩條鍵值對
5. 小結
這節課我們學習了函數的參數,參數這個概念是函數使用中不可缺少的一環。在函數定義時的參數叫做"形參",而在函數調用時的參數叫做"實參"。一定要分清這兩個概念。