1. 程式人生 > Python入門教學 >20 Python 中的函式引數

20 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 函式沒有任何位置引數

案例演示 預覽 複製 複製成功!
def hello_world
(): print('hello') print('world') hello_world()
執行案例 點選 "執行案例" 可檢視線上執行效果

程式執行輸出如下:

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):
    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 個數的累加和,程式碼如下:

案例演示 預覽 複製 複製成功!
def add(a, b):
    return a + b

add(1, 2)
執行案例 點選 "執行案例" 可檢視線上執行效果

編寫計算 3 個數的累加和函式,程式碼如下:

案例演示 預覽 複製 複製成功!
def add3(a, b, c):
    return a + b + c

add3(1, 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 例子

假設需要通過兩種方式來建立一個人的姓名:

  1. 直接給出人的姓名,需要一個引數:full_name

    • 例子,如果 full_name 等於 ‘ZhangSan’,則用這種方式建立的姓名是 ‘ZhangSan’
  2. 分別給出人的姓和名,需要兩個引數: 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 and 'last_name' in kw:
        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
  • 在第 12 行,通過 “直接給出人的姓名” 的方式呼叫 create_full_name
    • 傳遞關鍵字引數 full_name = ‘ZhangSan’
    • 關鍵字引數被合併入一個字典 kw_args
    • 字典 kw_args 中包含一條鍵值對
  • 在第 12 行,通過 “分別給出人的姓和名” 的方式呼叫 create_full_name
    • 傳遞關鍵字引數 first_name = ‘Li’、last_name = ‘Si’
    • 關鍵字引數被合併入一個字典 kw_args
    • 字典 kw_args 中包含兩條鍵值對

5. 小結

這節課我們學習了函式的引數,引數這個概念是函式使用中不可缺少的一環。在函式定義時的引數叫做"形參",而在函式呼叫時的引數叫做"實參"。一定要分清這兩個概念。