提示:上一篇文章介紹了Python中函數的基本使用,本篇文章主要說明一下Python函數實參的傳遞方式。
1、位置參數
位置參數:調用函數時根據函數定義的參數位置來傳遞參數。
def user_info(name, age, gender):
print(f'您的名字是{name}, 年齡是{age}, 性別是{gender}')
# 調用函數
user_info('TOM', 20, '男')
注意:傳遞和定義參數的順序及個數必須一致。就是將對應位置的實參復制給對應位置的形參,第一個實參賦值給第一個形參,第二個實參賦值給第二個形參,以此類推。
示例:
def user_info(name, age, gender):
print(f'您的名字是{name}, 年齡是{age}, 性別是{gender}')
# 1.調用函數,傳遞的參數個數不正確
# 結果:TypeError: user_info() missing 1 required positional argument: 'gender'
user_info('TOM', 20)
# 2.調用函數,傳遞的參數的順序不正確
# 不會報錯,但輸出的內容完全歧義。
# 結果:您的名字是男, 年齡是TOM, 性別是20
user_info('男', 'TOM', 20)
2、關鍵字參數
可以不按照形參定義的順序去傳遞,而直接根據參數名去傳遞參數。
函數調用,通過鍵=值
形式加以指定。
可以讓函數更加清晰、容易使用,同時也清除了參數的需求。
def user_info(name, age, gender):
print(f'您的名字是{name}, 年齡是{age}, 性別是{gender}')
# 正確用法
user_info('Rose', age=20, gender='女')
user_info('小明', gender='男', age=16)
# 位置參數必須寫在關鍵字參數的前面
# 結果:SyntaxError: positional argument follows keyword argument
user_info(gender='男', age=16, "孫悟空")
# 位置參數必須寫在關鍵字參數的前面,同時位置參數的順序也要對應
# 結果:TypeError: user_info() got multiple values for argument 'age'
user_info("孫悟空", '男', age=16)
# 格式正確,但是位置參數的順序不正確,結果也會產生歧義。
# 結果:您的名字是20, 年齡是孫悟空, 性別是男
user_info(20, "孫悟空", gender='男')
"""
總結:定義參數時,位置參數和關鍵字參數,盡量統一使用一種。
"""
注意:
- 位置參數和關鍵字參數可以混合使用。
- 函數調用時,如果有位置參數時,位置參數必須在關鍵字參數的前面,但關鍵字參數之間不存在先后順序。
3、缺省參數(默認參數)
缺省參數也叫默認參數,用於定義函數時,為參數提供默認值,調用函數時可不傳該默認參數的值。
提示:所有位置參數必須出現在默認參數前(因為默認參數的格式和關鍵字參數格式一樣,所以都要寫在所有參數之后),包括函數定義和調用。
def user_info(name, age, gender='男'):
print(f'您的名字是{name}, 年齡是{age}, 性別是{gender}')
# 沒有為缺省參數傳值,表示使用默認值。
user_info('TOM', 20)
# 為缺省參數傳值,使用這個值,即修改了默認值。
user_info('Rose', 18, '女')
注意:函數調用時,如果為缺省參數傳值則修改默認參數值,否則使用這個默認值。
4、不定長參數(可變參數)
不定長參數也叫可變參數。用於不確定調用的時候會傳遞多少個參數(不傳參也可以)的場景。此時,可用包裹位置參數,或者包裹關鍵字參數,來進行參數傳遞,會顯得非常方便。
(1)包裹位置傳遞
"""
1.在定義函數時,可以在形參前邊加上一個*,這樣這個形參將會獲取到所有的實參,
它將會將所有的實參保存到一個元組中
2.*args說明:*一定要寫,args表示形參,可以自定義名稱。
但在實際工作中,一般默認使用*args做為不定長包裹位置傳遞參數的表示,不做修改。
"""
def user_info(*args):
print(args)
# ('TOM',)
user_info('TOM')
# ('TOM', 18)
user_info('TOM', 18)
# ()
user_info()
注意:傳進的所有參數都會被
args
變量收集,它會根據傳進的所有的位置實參,合並為一個元組(tuple
),args
是元組類型,這就是包裹位置傳遞。(這個過程也叫裝包或者組包)
小應用:
# 定義一個函數,可以求任意個數字的和
def sum(*nums):
# 定義一個變量,來保存結果
result = 0
# 遍歷元組,並將元組中的數進行累加
for n in nums:
result += n
print(result)
sum(123, 456, 789, 10, 20, 30, 40)
注意事項:
# 注意事項1
# 帶星號的形參只能有一個
# 帶星號的參數,可以和其他參數配合使用
# 第一個參數給a,第二個參數給b,剩下的都保存到c的元組中
def fn2(a, b, *c):
print('a =', a)
print('b =', b)
print('c =', c)
fn2(1, 2, 3, 4, 5)
"""
輸出結果:
a = 1
b = 2
c = (3, 4, 5)
"""
# 注意事項2
# 可變參數不是必須寫在最后,但是注意,
# 帶*的參數后的所有參數,必須以關鍵字參數的形式傳遞
# 第一個參數給a,剩下的位置參數給b的元組,c必須使用關鍵字參數
def fn2(a, *b, c):
print('a =', a)
print('b =', b)
print('c =', c)
# TypeError: fn2() missing 1 required keyword-only argument: 'c'
# fn2(1, 2, 3, 4, 5) # 報錯
fn2(1, 2, 3, 4, c=5)
"""
輸出結果:
a = 1
b = (2, 3, 4)
c = 5
"""
# 注意事項3
# 所有的位置參數都給a,b和c必須使用關鍵字參數,
# 且必須寫在最后。
def fn2(*a, b, c):
print('a =', a)
print('b =', b)
print('c =', c)
fn2(1, 2, 3, b=4, c=5)
"""
輸出結果:
a = (1, 2, 3)
b = 4
c = 5
"""
# 注意事項4
# 如果在形參的開頭直接寫一個*,
# 則要求我們的所有的參數必須以關鍵字參數的形式傳遞。
def fn2(*, a, b, c):
print('a =', a)
print('b =', b)
print('c =', c)
fn2(a=3, b=4, c=5)
"""
輸出結果:
a = 3
b = 4
c = 5
"""
# 注意事項5
# *形參只能接收位置參數,而不能接收關鍵字參數
def fn3(*a):
print('a =', a)
# TypeError: fn3() got an unexpected keyword argument 'a'
fn3(a=3, b=4, c=5)
(2)包裹關鍵字傳遞
"""
**kwargs說明:**一定要寫,args表示形參,可以自定義名稱。
但在實際工作中,一般默認使用**kwargs做為不定長包裹關鍵字傳遞參數的表示,不做修改。
"""
# 收集所有關鍵字參數,它會將這些參數統一保存到一個字典中返回。
# 字典的key就是參數的名字,字典的value就是參數的值
def user_info(**kwargs):
print(kwargs)
# {'name': 'TOM', 'age': 18, 'id': 110}
# 關鍵字不能加引號,應為關鍵字對應的是形參。
user_info(name='TOM', age=18, id=110)
# 包裹關鍵字傳遞只能有一個,並且必須寫在所有參數的最后
# 實參可以不按順序傳遞
def fn3(b, c, **a):
print('a =', a, type(a))
print('b =', b)
print('c =', c)
fn3(e=10, b=1, d=2, c=3, f=20)
"""
輸出結果:
a = {'e': 10, 'd': 2, 'f': 20} <class 'dict'>
b = 1
c = 3
"""
綜上:無論是包裹位置傳遞還是包裹關鍵字傳遞,都是一個組包的過程(組包簡單的說,就是收集分散的參數,返回一個整體數據)。關於組包對應就是拆包,在之前的文章【Python元組】中有介紹,可以對應的查看。
5、位置參數、默認參數、可變參數的混合使用
參數定義與調用順序的基本原則是:位置參數,默認參數,包裹位置,包裹關鍵字。(定義和調用都應遵循)
提示:默認參數與包裹位置參數可以根據需求進行位置調換。
def user_info(name, age, sex=1, *args, **kargs):
print(name, age, sex, args, kargs)
user_info('TOM', 18, 2, 'music', 'sport', id=101)
# 輸出結果
# TOM 18 2 ('music', 'sport') {'id': 101}
6、拓展:參數解包
關於組包對應就是拆包,在之前的文章【Python元組】中有介紹,可以對應的查看。
(1)通過包裹位置對一個元組進行解包
操作方式:使用*
號。
如下示例:
# 參數的解包(拆包)
def fn4(a, b, c):
print('a =', a)
print('b =', b)
print('c =', c)
# 創建一個元組
t = (10, 20, 30)
# 我們直接傳遞t,會報錯
# TypeError: fn4() missing 2 required positional arguments: 'b' and 'c'
# fn4(t)
# 而以前我們是這樣拆包的
# fn4(t[0], t[1], t[2])
"""
輸出結果:
a = 10
b = 20
c = 30
"""
# *號拆包
# 傳遞實參時,也可以在序列類型的參數前添加星號,
# #這樣他會自動將序列中的元素依次作為參數傳遞。
# 這里要求序列中元素的個數必須和形參的個數的一致
fn4(*t)
"""
輸出結果:
a = 10
b = 20
c = 30
"""
(2)通過包裹關鍵字對一個字典進行解包
操作方式:使用**
號。
如下示例:
# 參數的解包(拆包)
def fn4(a, b, c):
print('a =', a)
print('b =', b)
print('c =', c)
# 創建一個字典
d = {'a': 100, 'b': 200, 'c': 300}
# 通過 **來對一個字典進行解包操作
# 字典中的key要和函數的形參一一對應。
fn4(**d)
"""
輸出結果:
a = 100
b = 200
c = 300
"""