第一部分裝飾器,接觸很久,沒理會原理。慚愧。
第二部分裝飾器傳參的小實踐。
第三部分閉包的理解,如果有錯誤,留著,以後再說。
其本意就是在不改變原函式的基礎上,對函式新增功能。用途呢,aop思想,你說是吧。
乙個自己寫裝飾器的例子:
# 定義裝飾器
# 這種寫法比較適合簡單的包裹,只是會把real_func前面「裹住」,
# 在進入realfunc前進行處理
defdecorate
(real_func)
:def()
:print
('this is decoration function'
)# do sth
return real_func(
)
比較一下可以看到,第一種decorate函式返回的是乙個函式而不是乙個值,函式名+括號的時候函式才會執行,所以得func_to_run()
才能執行。
那顯然,返回值不能是函式(函式不是「第一類變數」)的語言自然沒有這種用法。
裝飾器的使用,接上文
# 定義帶有裝飾器的函式
@decorate
def whatever():
print('this is real function')
# 執行函式的時候會把裝飾器函式也執行
whatever()
#裝飾器是python的語法糖,以上寫法等同於以下
func_to_run=decorate(whatever)
func_to_run()
如果單單看第一種執行的順序的話
decorate收入whatever作為引數
然後whatever函式執行自己的邏輯 )
whatever(
)是的是的,那為什麼不直接這樣順序寫呢?不是說了嗎aop啊,在不改動原來函式**的基礎上對原函式新增功能。
另:另一種我比較喜歡的裝飾器的寫法,
defdecorate
(real_func)
:def()
:# do sth code
real_func(
)# do sth code
return
以下**寫了乙個guard裝飾器,保證此次函式執行多次進行嘗試,嘗試次數有限,成功繼續下一步,超限退出。
def
guard
(operation_func)
: @functools.wraps(operation_func)
def(
*args,
**kwargs)
: succeed=
false
cnt=
0while
not succeed and cnttry:
operation_func(
*args,
**kwargs)
succeed=
true
except exception as e:
cnt+=
1if cnt==retry_time:
print
("sorry, max retry reached. exit..."
) exit(0)
print
("error: {}, retrying {}..."
.format
(e,cnt+1)
) time.sleep(
2)
然而在使用的時候,driver這個返回值卻是none。
from web import webdriver
# 函式定義
# 執行
driver=makeconnection(
)print
(driver)
# 列印的是none
怎麼driver沒有被返回出來?
其實是因為裝飾器在呼叫makeconnection的時候沒有接收並且return引數,儘管makeconnection返回了引數,但是裝飾器函式沒有接收它,更別談返回了。
所以需要修改裝飾器,讓它接收引數並且傳遞。
這是我們需要注意的點。即便是函式本身return了引數,如果裝飾器不接著傳遞下去,引數會在路上被「丟掉」。
修改如下:
def
guard
(operation_func)
: @functools.wraps(operation_func)
def(
*args,
**kwargs)
: succeed=
false
cnt=
0while
not succeed and cnttry:
# 接收引數並且傳遞
elem=operation_func(
*args,
**kwargs)
succeed=
true
if succeed:
return elem
except exception as e:
cnt+=
1if cnt==retry_time:
print
("sorry, max retry reached. exit..."
) exit(0)
print
("error: {}, retrying {}..."
.format
(e,cnt+1)
) time.sleep(
2)
貌似離散數學的閉包,和你們程式設計裡面談的閉包沒有關係啊……
可參考這個知乎
這個概念啊,很操蛋哦,是個模糊的概念,想找起源都找不到。如有,麻煩告知我我再去看看。
其廣泛流傳的概念有兩種。
「在函式中訪問到函式外部的變數,這種情況即可稱作閉包」,出處見這裡,就像這個例子。
defa(
):value_a=
199defb(
):print
(value_a)
這玩意就算是個小閉包了。b的作用域中訪問到了value_a,只不過這樣太傻了,而且這樣寫法沒什麼用。
這個概念更加具體些,體現在第乙個概念的具體用途上:「在執行過程完畢後返回函式,將函式和其上下文保留,即形成閉包」,出處這裡。不過這種用途,個人認為,只能在返回值可以是函式的語言上有所體現。
這個說法很搞笑,不過也挺生動的,是對這個概念的體現。
這個概念的例子更符合實際用途:
返回的函式(function),攜帶著function外部的environment的量到了environment外面。
def
enrivonment()
: a=
100def
function()
: b=
200return a+b
return function
func_with_enrivonment=enrivonment(
)print
(func_with_enrivonment(
))
Python 裝飾器 ,閉包
1 裝飾器 不改變被裝飾的函式情況下附加一些功能 本質是函式,用於裝飾其他函式,附加一些本身所沒有的功能 實質 是乙個函式 引數 是你要裝飾的函式名 並非函式呼叫 返回 是裝飾完的函式名 也非函式呼叫 作用 為已經存在的物件新增額外的功能 特點 不需要對物件做任何的 上的變動 例1 計算執行時長 i...
python裝飾器和閉包
下面幾個部落格有裝飾器的講解,也包含了裝飾器幾種情況的例子,比如說被裝飾的函式帶引數,裝飾器本身帶引數等。理解python中的裝飾器 python裝飾器學習 例子 其實裝飾器跟設計模式中的裝飾器模式基本一樣,就是在已有的函式上新增新的功能,這也是自己對裝飾器的一點簡陋的理解了。下面是自己寫的簡單例子...
python閉包和裝飾器
要理解裝飾器,就要明白閉包 要明白閉包,首先就要從高階函式和作用域說起 說道作用域,一般會談到legb規則。所謂的legb l locals,當前命名空間 區域性作用域 e enclosing,外部函式的命名空間 外部作用域 g global,全域性的命名空間 b bulit in,內建的命名空間平...