1、可接受任意數量參數的函數
【問題】
你想構造一個可接受任意數量參數的函數
【就決方案】
爲了能使一個函數接受任意數量的位置參數,可以使用一個 * 參數
def avg(first,*rest)
return (first + sum(rest)) / (1 + len(rest))
avg(1,2)
avg(1,2,3,4)
爲了接受任意數量的關鍵字參數,使用一個以 ** 開頭的參數。
def a(x,*args,y):
pass
def b(x, *args,y,**kwargs):
pass
2、只接受關鍵字參數的函數
【問題】
你希望函數的某些參數強制使用關鍵字參數傳遞
【解決方案】
將強制關鍵字參數放到某個*參數或者單個星後面就能達到這種效果
def recv(maxsize,*,block):
...
pass
recv(1024,True) #TypeError
recv(1024,block=True) #ok
利用這種技術,我們還能在接受任意多個位置參數的函數中指定關鍵字參數,比如:
def mininum(*values,clip=None):
m = min(values)
if clip is not None:
m = clip if clip > m else m
return m
mininum(1,5,2,-5,10) # returns -5
mininum(1,5,2,-5,10,clip=0) # returns 0
3、給函數參數增加元信息
【問題】
你寫好一個函數,然後想爲這個函數的參數增加一些額外信息,這樣的話其他使用者就能清楚的知道這個函數應該怎麼使用。
【解決方案】
使用函數參數註解是一個很好的辦法,它能提示程序員應該怎樣正確使用這個函數。例如,下面有一個被註解了的函數
def add(x:int, y:int) -> int:
return x + y
4、定義匿名或內聯函數
【問題】
你想爲 sort()操作創建一個很短的回調函數,但又不想用 def 去寫一個單行函數,而是希望通過否個快捷方式以內聯方式來創建這個函數
【解決方案】
當一個函數很簡單,僅僅是計算一個表達式的值的時候,就可以使用 lambda 表達式來代替。
add = lambda x,y:x+y
add(2,3)
def add(x,y):
return x + y
上面這兩種方式效果是一樣的
5、匿名函數捕獲變量值
【問題】
你用lambda定義一個匿名函數,並想在定義時捕獲到某些變量的值
【解決方案】
我們先看看代碼的效果
x = 10
a = lambda y:x + y
x = 20
b = lambda y:x + y
現在我問你,a(10)和b(10)返回什麼結果?如果你認爲是20和30,那你就錯了 。
a(10)
30
b(10)
30
這次中的奧祕就在於 lambda表達式中 x 是一個自由變量,在運行時綁定值,而不是定義的時候綁定值,這跟函數的默認參數定義是不同的。因此在調用lambda時,x是執行時的值。
如果想讓某個匿名函數在定義的時候就捕獲到值,可以將那個參數值設定爲默認參數,就像下面這樣
x = 10
a = lambda y,x=x,x+y
x = 20
b = lambda y,x=x,x+y
a(10)
# 20
b(10)
# 30
通過一個循環或列表推導中創建一個lambda表達式列表,並期望函數在定義時就記住每次的迭代值。
funcs=[lambda x:x+n for n in range(5)]
for f in funcs:
print(f(0))
#4
#4
#4
#4
#4
funs=[lambda x,n=n:x+n for n in range(5)]
for f in funcs:
print(f(0))
#0
#1
#2
#3
#4
通過使用函數默認值形式參數,lambda函數在定義時就能綁定值。