一. 位置參數(shù)與關(guān)鍵字參數(shù)
def say_hi(name,who):
print("{} say hi to {}".format(name,who))
say_hi("jose","bill") #正確
say_hi(who="bill","jose") #錯(cuò)誤
say_hi(name="jose","bill") #錯(cuò)誤
say_hi('bill',name="jose") #正確
結(jié)論很簡(jiǎn)單埂蕊,有位置參數(shù)時(shí)谚中,位置參數(shù)必須在關(guān)鍵字參數(shù)的前面,并且關(guān)鍵字參數(shù)之間不存在先后順序。
二. *args和**kwarg
可變位置參數(shù)和可變關(guān)鍵字參數(shù)是不確定要向函數(shù)傳參與否或者傳幾個(gè)參數(shù)時(shí)使用的:
def func(*args):
...
# func()
# func(a)
# func(a, b, c)
按照傳參順序生成元組蔑担,就像把幾個(gè)位置參數(shù)打成包裹。
def func(**kwargs):
...
# func(a = 1)
# func(a = 1, b = 2)
按照傳參順序生成一個(gè)字典枷遂。也就是把可變關(guān)鍵字參數(shù)打成包裹漆枚。
def foo(x,*args,a=4,**kwargs): #使用默認(rèn)參數(shù)時(shí),注意默認(rèn)參數(shù)的位置要在args之后kwargs之前
print(x)
print(a)
print(args)
print(kwargs)
foo(1,5,6,7,8,y=2,z=3) #調(diào)用函數(shù)膀曾,不修改默認(rèn)參數(shù)
1 #x的值
4 #a的值
(5, 6, 7, 8) #*args的值
{'y': 2, 'z': 3} ##kwargs的值
三. 裝飾器
聽(tīng)說(shuō)裝飾器必問(wèn)县爬?畢竟是在python中應(yīng)用特別廣泛的代表,今天好好研究一下添谊。
首先要明確的是财喳,裝飾器本質(zhì)上也是一個(gè)python函數(shù),可以讓其他函數(shù)在不需要做任何代碼變動(dòng)的前提下增加額外功能斩狱。一個(gè)簡(jiǎn)單的例子就是為函數(shù)增加他的名字耳高。
def fun1(para):
print('abc')
print(fun1.__name__)
如果不僅僅有fun1,還有fun2,fun3我們統(tǒng)稱fun,我們?yōu)槊總€(gè)函數(shù)都增加一個(gè)顯示名字的方法,你肯定知道一個(gè)個(gè)加是不現(xiàn)實(shí)的喊废,而且也很麻煩祝高。可能你想到了創(chuàng)建一個(gè)新函數(shù)污筷。
def log(fun):
print(fun.__name__)
fun()
但是這樣的話其實(shí)也不可避免的改動(dòng)了函數(shù)聲明工闺,比如原來(lái)使用fun1(para)就能完成的任務(wù),現(xiàn)在要使用log(fun1(para))瓣蛀。
那么如果你有很多別的語(yǔ)言的學(xué)習(xí)經(jīng)驗(yàn)陆蟆,可能已經(jīng)注意到了一點(diǎn)不同,那就是python的函數(shù)也可以當(dāng)作普通的對(duì)象傳遞給另一個(gè)函數(shù)惋增,有了這一點(diǎn)前提叠殷,裝飾器就有了一席之地。
def log(func):
def real():
print("%s is running" % func.__name__)
return func()
return real
@log
def abc():
print('abc')
#abc = log(abc)
abc()
可以看到诈皿,裝飾器與bar = log(bar)的作用實(shí)際上是一樣的林束。
除了函數(shù)裝飾器之外還有類裝飾器像棘,原理是一樣的,只不過(guò)類裝飾器中需要有一個(gè)“call”方法:
class log(object):
def __init__(self, func):
self._func = func
def __call__(self):
print ('abc')
self._func()
# @Foo
def abc():
print ('abc')
abc = log(abc)
abc()