匿名函數(shù)
1)匿名函數(shù)有個限制,就是只能有一個表達式,不用寫return,返回值就是該表達式的結(jié)果。
2)因為沒有名字,不必擔(dān)心函數(shù)名沖突
3)可以把匿名函數(shù)賦值給一個變量,再利用變量來調(diào)用該函數(shù)
4)同樣,也可以把匿名函數(shù)作為返回值返回,比如:
def build(x, y):
? ? return lambda: x * x + y * y
裝飾器
1)函數(shù)對象有一個__name__屬性,可以拿到函數(shù)的名字
2)這種在代碼運行期間動態(tài)增加功能的方式,稱之為“裝飾器”(Decorator),decorator就是一個返回函數(shù)的高階函數(shù)
def log(func):
? ? def wrapper(*args, **kw):
? ? ? ? print('call %s():' % func.__name__)
? ? ? ? return func(*args, **kw)
? ? return wrapper
觀察上面的log,因為它是一個decorator,所以接受一個函數(shù)作為參數(shù),并返回一個函數(shù)。我們要借助Python的@語法,把decorator置于函數(shù)的定義處:
@log
def now():
? ? ?print('2015-3-25')
調(diào)用now()函數(shù),不僅會運行now()函數(shù)本身,還會在運行now()函數(shù)前打印一行日志:
>>> now()
call now():
2015-3-25
把@log放到now()函數(shù)的定義處,相當(dāng)于執(zhí)行了語句:
now= log(now)如果decorator本身需要傳入?yún)?shù),那就需要編寫一個返回decorator的高階函數(shù),寫出來會更復(fù)雜。比如,要自定義log的文本:
def log(text):
? ? def decorator(func):
? ? ? ? def wrapper(*args, **kw):
? ? ? ? ? ? print('%s %s():' % (text, func.__name__))
? ? ? ? ? ?return func(*args, **kw)
? ? ? ? return wrapper
? ? return decorator
這個3層嵌套的decorator用法如下:
@log('execute')
def now():
? ? print('2015-3-25')
執(zhí)行結(jié)果如下:
>>> now()
execute now():
2015-3-25
和兩層嵌套的decorator相比,3層嵌套的效果是這樣的:
>>> now = log('execute')(now)
首先執(zhí)行l(wèi)og('execute'),返回的是decorator函數(shù),再調(diào)用返回的函數(shù),參數(shù)是now函數(shù),返回值最終是wrapper函數(shù)。
3)因為返回的那個wrapper()函數(shù)名字就是'wrapper',所以,需要把原始函數(shù)的__name__等屬性復(fù)制到wrapper()函數(shù)中,否則,有些依賴函數(shù)簽名的代碼執(zhí)行就會出錯。
即在總的編寫前加上:
import functools
在wrapper定義前加上:
@functools.wraps(func)
使用時在案例代碼上進行修改可以簡單得到想要的效果
自己打一遍理解起來更快