匿名函數(shù): lambda
不需要顯式地定義函數(shù)瓮具,直接傳入匿名函數(shù)更方便。
>>> list(map(lambda x: x * x, [1, 2, 3, 4, 5, 6, 7, 8, 9]))
[1, 4, 9, 16, 25, 36, 49, 64, 81]
關(guān)鍵字lambda
表示匿名函數(shù),冒號(hào)前面的x表示函數(shù)參數(shù)
限制:只能有一個(gè)表達(dá)式名党,不用寫return叹阔,返回值就是該表達(dá)式的結(jié)果。
好處:函數(shù)沒有名字传睹,不必?fù)?dān)心函數(shù)名沖突耳幢。
把匿名函數(shù)賦值給一個(gè)變量,再利用變量來調(diào)用該函數(shù)
>>> f = lambda x: x * x
>>> f
<function <lambda> at 0x101c6ef28>
>>> f(5)
25
同樣欧啤,也可以把匿名函數(shù)作為返回值返回睛藻,比如:
def build(x, y):
return lambda: x * x + y * y #返回的是個(gè)函數(shù) 調(diào)用build(2,3)()
裝飾器(Decorator)
裝飾器(Decorator):要增強(qiáng)某函數(shù)的功能,但又不希望修改該函數(shù)的定義邢隧,這種在代碼運(yùn)行期間動(dòng)態(tài)增加功能的方式店印,稱之為“裝飾器”(Decorator)
1)函數(shù)的__name__
屬性,獲取函數(shù)名府框。注:__
是兩個(gè)_
- 栗子
#定義一個(gè)能打印日志的decorator
def log(func):
def wrapper(*args,**kw):
print('call %s():'%func.__name__)
return func(*args,**kw)
return wrapper
#log函數(shù)接受一個(gè)函數(shù)作為參數(shù)吱窝,并返回一個(gè)函數(shù)。
*args,**kw
前一個(gè)是可變參數(shù)迫靖,就是隨便傳入的參數(shù)個(gè)數(shù)不定院峡,后面那個(gè)是關(guān)鍵字參數(shù),個(gè)數(shù)不定系宜,在函數(shù)內(nèi)部自動(dòng)組裝為一個(gè)dict照激。
這個(gè)東西在函數(shù)里,感覺沒發(fā)揮啥作用盹牧。
@log # 放在now()函數(shù)出相當(dāng)于執(zhí)行了now=log(now)
def now():
print('2017-5-11')
>>> now() #即會(huì)運(yùn)行now()函數(shù)俩垃,還會(huì)在運(yùn)行now()前打印一行日志
call now(): --->這就是裝飾器里定義的,先返回了這個(gè)
2015-3-25
@log
相當(dāng)于執(zhí)行now=log(now)
汰寓,由于log()是一個(gè)decorator口柳,返回一個(gè)函數(shù),所以有滑,原來的now()函數(shù)仍然存在跃闹,只是現(xiàn)在同名的now變量指向了新的函數(shù),于是調(diào)用now()將執(zhí)行新函數(shù)毛好,即在log()函數(shù)中返回的wrapper()函數(shù)望艺。
wrapper()函數(shù)的參數(shù)定義是(*args, **kw)
,因此肌访,wrapper()函數(shù)可以接受任意參數(shù)的調(diào)用找默。在wrapper()函數(shù)內(nèi),首先打印日志吼驶,再緊接著調(diào)用原始函數(shù)惩激。
- 栗子
如果decorator本身需要傳入?yún)?shù)店煞,則需要編寫一個(gè)返回decorator的高階函數(shù)
def log(text):
def decorator(func):
def wrapper(*args,**kw):
print('%s %s():'%(text,func.__name__))
return func(*args,**kw)
return wrapper
return decorator
寫到這里給我的感覺就是:外層的函數(shù)不斷返回內(nèi)層的函數(shù)
先最外層的log函數(shù)里傳入?yún)?shù),然后返回第二層的decorator
#以下是調(diào)用
@log('execute')
def now():
print('2017-5-11')
now() #execute now(): 2017-5-11
但是現(xiàn)在
>>> now.__name__ #返回的那個(gè)wrapper()函數(shù)名字就是'wrapper',所以現(xiàn)在now函數(shù)的名字變了
'wrapper
所以需要把原始函數(shù)的name等屬性復(fù)制到wrapper()函數(shù)中咧欣,否則浅缸,有些依賴函數(shù)簽名的代碼執(zhí)行就會(huì)出錯(cuò)。
利用Python內(nèi)置函數(shù)functools.wraps
完整的寫法:
import functools
def log(text):
def decorator(func):
@functools.wraps(func) ###這個(gè)魄咕。衩椒。。呃哮兰。毛萌。。
def wrapper(*args, **kw):
print('%s %s():' % (text, func.__name__))
return func(*args, **kw)
return wrapper
return decorator
記得外層的函數(shù)先運(yùn)行喝滞,層層套進(jìn)
還沒完阁将。。右遭。還沒完做盅。。窘哈。這么膚淺的理解吹榴,我要記得來第二波。滚婉。图筹。