閉包是帶有上下文的函式,可以儲存函式的狀態資訊,比如巢狀函式可以儲存外層函式的變數。一般情況下,如果乙個函式結束,函式的內部所有東西都會釋放掉,還給記憶體,區域性變數都會消失。但是閉包是一種特殊情況,如果外函式在結束的時候發現有自己的臨時變數將來會在內部函式中用到,就把這個臨時變數繫結給了內部函式,然後自己再結束。
正因為閉包可以儲存狀態,而裝飾器本質上就是為物件附加額外的屬性(狀態)。所以,借助閉包就能輕易地實現裝飾器了。
import time
from functools import wraps
def hello():
print("say hello")
def run_time(func):
@wraps(func)
def wrap():
start_time=time.time()
func()
end_time=time.time()
print(func.__name__," excution time: ms\n".format((end_time-start_time)*1000))
return wrap;
hello2=run_time(hello)
hello2()
## say hello
# hello excution time:0.99 ms
#使用@語法糖形式
@run_time
def cat():
print("miao~~~")
cat()
## miao~~~
# cat excution time:0.5 ms
上面的例子我直接把"@wraps"也寫出來了 ,他的作用就是把被裝飾的函式(傳入的函式)的一些屬性賦值給裝飾器函式(返回那個函式)。
帶引數的裝飾器(帶引數的裝飾器就是在原閉包的基礎上又加了一層閉包):
def func_args(pre='xiaoqiang'):
def w_test_log(func):
def inner():
print('...記錄日誌...visitor is %s' % pre)
func()
return inner
return w_test_log
# 帶有引數的裝飾器能夠起到在執行時,有不同的功能
# 先執行func_args('wangcai'),返回w_test_log函式的引用
# @w_test_log
# 使用@w_test_log對test_log進行裝飾
@func_args('wangcai')
def test_log():
print('this is test log')
test_log()
## ...記錄日誌...visitor is wangcai
# this is test log
通用裝飾器(匹配任意的函式引數):
def w_test(func):
def inner(*args, **kwargs):
ret = func(*args, **kwargs)
return ret
return inner
@w_test
def test():
print('test called')
@w_test
def test1():
print('test1 called')
return 'python'
@w_test
def test2(a):
print('test2 called and value is %d ' % a)
test()
test1()
test2(9)
參考部落格(閉包與裝飾器):
參考部落格(裝飾器與wrap):
Python 閉包和裝飾器 學習筆記
外部函式接收姓名引數 defconfig name name 內部函式儲存外部函式的引數,並且完成資料顯示的組成 definner msg print name msg 外部函式要返回內部函式 return inner 建立閉包物件 tom config name tom jane config n...
python閉包與裝飾器
首先閉包函式我的理解是,乙個函式內可以巢狀定義乙個函式,並將巢狀定義的函式返回 如果不返回執行完函式物件也就銷毀了 巢狀函式可以接收外部函式的引數,不同引數就可以變更巢狀函式的功能,返回不同功能的巢狀函式物件。以下是閉包函式簡單示例,如果inner函式不接收outer的引數x也就沒有意義了,一定要返...
Python閉包與裝飾器
一.閉包 如果乙個內嵌函式中引用了外部函式中的變數 非全域性變數 那麼該內嵌函式稱之為閉包 也就是將組成函式的語句和這些語句的執行環境打包在一起時,得到的物件 閉包滿足的三個條件 1.必須是內嵌函式 2.外層函式返回值是內嵌函式 3.內嵌函式引用外層函式變數 def funx x def funy ...