【python筆記】函式_03_函式的引數
阿新 • • 發佈:2018-12-13
實參:鑑於函式定義中可能包含多個實參,因此函式呼叫可能包含多個實參。
- 向函式傳遞實參函式的方式很多,可使用位置實參,這就要求實參的順序與形參的順序相同
- 也可使用關鍵字實參,其中每個實參都有變數名和值組成;
- 還可使用列表和字典
1.位置實參
- 定義:你呼叫函式時,python必須將函式呼叫中的每個實參都關聯到函式定義的一個形參。為此,最簡單的關聯方式是基於實參的順序。這種關聯方式被稱為位置實參
- 可以呼叫函式多次
- 位置引數的順序很重要
2.關鍵字實參
- 定義:關鍵字實參是傳遞給函式的名稱-值對。你直接在實參中將名稱和值關聯起來了,因此向引數傳遞實參時不會混淆。關鍵字實參讓你無需考慮函式呼叫中的實參順序,還清楚地指出了函式呼叫中各個值的用途。
def describe_pet(animal_type, pet_name):
"""顯示寵物的資訊"""
print("\nI have a " + animal_type + ".")
print("My " + animal_type + "'s name is " + pet_name.title() + ".")
describe_pet(animal_type='hamster', pet_name='harry')
- 注意:使用關鍵字實參時,務必準確地指出函式定義中的形參名。
3.預設引數
- 定義:編寫函式時,可給每個形參指定預設值。在呼叫函式中給形參提供了實參時,python將使用指定的實參值;否則,將使用形參的預設值。因此,給形參指定預設值後,可在函式呼叫中省略相應的實參。使用預設值可簡化函式呼叫,還可以清楚地指出函式的典型用法。
def describe_pet(pet_name, animal_type='dog'):
"""顯示寵物的資訊"""
print("\nI have a " + animal_type + ".")
print("My " + animal_type + "'s name is " + pet_name.title() + ".")
describe_pet(pet_name='willie')
- 注意:使用預設值時,在形參列表中必須先列出沒有預設值的形參,再列出有預設值的實參。這讓Python依然能夠正確地解讀位置實參。
def add_end(L=[]):
L. append('END')
return L
>>> add_end()
['END']
>>> add_end()
['END', 'END']
>>> add_end()
['END', 'END', 'END']
- 定義預設引數要牢記一點:預設引數必須指向不變物件!
def add_end(L=None):
if L is None:
L = []
L.append('END')
return L
>>> add_end()
['END']
>>> add_end()
['END']
- 為什麼要設定
str 、None
這樣的不變物件呢? 因為不變物件一旦建立,物件內部的資料就不能被修改,這樣就減少了由於修改資料導致的錯誤。此外,由於物件不變,多工環境下同時讀取物件不需要加鎖,同時讀一點問題都沒有。我們在編寫程式時,如果可以設計一個不變物件,那就儘量設計成不變物件。
4.可變引數
- 定義:可變引數就是傳入的引數個數時可變的,可以是1個、2個、到任意個,還可以是0個。
- 我們把函式的引數改為可變引數:
def calc(*numbers):
sum = 0
for n in numbers:
sum = sum + n * n
return sum
- 定義可變引數和定義一個
list
或tuple
引數相比,僅僅在引數前面加了一個*號。在函式內部,引數numbers
接收到的是一個tuple
,因此,函式程式碼完全不變。但是,呼叫該函式時,可以傳入任意個引數,包括0個引數:
>>> calc(1, 2)
5
>>> calc()
0
- Python允許你在
list
或tuple
前面加一個*
號,把list
或tuple
的元素變成可變引數傳進去:
>>> nums = [1, 2, 3]
>>> calc(*nums)
14
5.關鍵字引數
- 關鍵字引數允許你傳入0個或任意個含引數名的引數,這些關鍵字引數在函式內部自動組裝為一個
dict
。 - **關鍵字引數有什麼用?**它可以擴充套件函式的功能。比如,在person函式裡,我們保證能接收到name和age這兩個引數,但是,如果呼叫者願意提供更多的引數,我們也能收到。試想你正在做一個使用者註冊的功能,除了使用者名稱和年齡是必填項外,其他都是可選項,利用關鍵字引數來定義這個函式就能滿足註冊的需求。
- 和可變引數類似,也可以先組裝出一個
dict
,然後,把該dict
轉換為關鍵字引數傳進去:
def person(name, age, **kw):
print('name:', name, 'age:', age, 'other:', kw)
>>> extra = {'city': 'Beijing', 'job': 'Engineer'}
>>> person('Jack', 24, **extra)
name: Jack age: 24 other: {'city': 'Beijing', 'job': 'Engineer'}
**extra
表示把extra
這個dict
的所有key-value
用關鍵字引數傳入到函式的**kw
引數,kw
將獲得一個dict
,注意kw
獲得的dict
是extra
的一份拷貝,對kw
的改動不會影響到函式外的extra。
6.命名關鍵字引數
- 如果要限制關鍵字引數的名字,就可以用命名關鍵字引數,例如,只接收
city
和job
作為關鍵字引數。這種方式定義的函式如下:
def person(name, age, *, city, job):
print(name, age, city, job)
- 和關鍵字引數
**kw
不同,命名關鍵字引數需要一個特殊分隔符*,*後面的引數被視為命名關鍵字引數。 - 呼叫方式如下:
>>> person('Jack', 24, city='Beijing', job='Engineer')
Jack 24 Beijing Engineer
- 如果函式定義中已經有了一個可變引數,後面跟著的命名關鍵字引數就不再需要一個特殊分隔符
*
了:
def person(name, age, *args, city, job):
print(name, age, args, city, job)
- 命名關鍵字引數必須傳入引數名,這和位置引數不同。如果沒有傳入引數名,呼叫將報錯:
>>> person('Jack', 24, 'Beijing', 'Engineer')
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: person() takes 2 positional arguments but 4 were given
-
由於呼叫時缺少引數名
city
和job
,Python直譯器把這4個引數均視為位置引數,但person()
函式僅接受2個位置引數。 -
命名關鍵字引數可以有預設值,從而簡化呼叫:
def person(name, age, *, city='Beijing', job):
print(name, age, city, job)
- 由於命名關鍵字引數city具有預設值,呼叫時,可不傳入city引數:
>>> person('Jack', 24, job='Engineer')
Jack 24 Beijing Engineer
- 使用命名關鍵字引數時,要特別注意,如果沒有可變引數,就必須加一個
*
作為特殊分隔符。如果缺少*
,Python直譯器將無法識別位置引數和命名關鍵字引數:
def person(name, age, city, job):
# 缺少 *,city和job被視為位置引數
pass
7.引數組合
- 在Python中定義函式,可以用必選引數、預設引數、可變引數、關鍵字引數和命名關鍵字引數,這5種引數都可以組合使用。但是請注意,引數定義的順序必須是:必選引數、預設引數、可變引數、命名關鍵字引數和關鍵字引數。
def f1(a, b, c=0, *args, **kw):
print('a =', a, 'b =', b, 'c =', c, 'args =', args, 'kw =', kw)
def f2(a, b, c=0, *, d, **kw):
print('a =', a, 'b =', b, 'c =', c, 'd =', d, 'kw =', kw)
>>> f1(1, 2)
a = 1 b = 2 c = 0 args = () kw = {}
>>> f1(1, 2, c=3)
a = 1 b = 2 c = 3 args = () kw = {}
>>> f1(1, 2, 3, 'a', 'b')
a = 1 b = 2 c = 3 args = ('a', 'b') kw = {}
>>> f1(1, 2, 3, 'a', 'b', x=99)
a = 1 b = 2 c = 3 args = ('a', 'b') kw = {'x': 99}
>>> f2(1, 2, d=99, ext=None)
a = 1 b = 2 c = 0 d = 99 kw = {'ext': None}
- 最神奇的是通過一個
tuple和dict
,你也可以呼叫上述函式:
>>> args = (1, 2, 3, 4)
>>> kw = {'d': 99, 'x': '#'}
>>> f1(*args, **kw)
a = 1 b = 2 c = 3 args = (4,) kw = {'d': 99, 'x': '#'}
>>> args = (1, 2, 3)
>>> kw = {'d': 88, 'x': '#'}
>>> f2(*args, **kw)
a = 1 b = 2 c = 3 d = 88 kw = {'x': '#'}
小結
- Python的函式具有非常靈活的引數形態,既可以實現簡單的呼叫,又可以傳入非常複雜的引數。
- 預設引數一定要用不可變物件,如果是可變物件,程式執行時會有邏輯錯誤!
- 要注意定義可變引數和關鍵字引數的語法:
*args
是可變引數,args
接收的是一個tuple
;**kw
是關鍵字引數,kw
接收的是一個dict
。- 以及呼叫函式時如何傳入可變引數和關鍵字引數的語法:
- 可變引數既可以直接傳入:
func(1, 2, 3)
,又可以先組裝list
或tuple
,再通過*args
傳入:func(*(1, 2, 3));
- 關鍵字引數既可以直接傳入:
func(a=1, b=2)
,又可以先組裝dict
,再通過**kw
傳入:func(**{'a': 1, 'b': 2})
。 - 使用
*args
和**kw
是Python的習慣寫法,當然也可以用其他引數名,但最好使用習慣用法。 - 命名的關鍵字引數是為了限制呼叫者可以傳入的引數名,同時可以提供預設值。
- 定義命名的關鍵字引數在沒有可變引數的情況下不要忘了寫分隔符
*
,否則定義的將是位置引數。