例項講解Python的函式閉包使用中應注意的問題

2022-10-04 21:48:45 字數 2706 閱讀 6781

昨天正當我用十成一陽指功力戳鍵盤、昏天暗地coding的時候,正好被人問了乙個問題,差點沒收好功,洪荒之力側漏震傷桌邊的人,廢話不多說,先上栗子(精簡版,只為說明問題):

from functools import wraps

from time import sleep

def retry(attempts=3, wait=2):

if attempts < 0 or attempts > 5:

retry_times = 3

else:

retry_times = attempts

if wait < 0 or wait > 5:

retry_wait = 2

else:

retry_wait = after

def retry_decorator(func):

@wraps(func)

def wrapped_function(*args, **kwargs)sqpwe:

while retry_times > 0:

try:

return func(*args, **kwargs)

except :

sleep(retry_wait)

程式設計客棧 retry_times -= 1

return wrapped_function

return retry_decorator

簡易版的retry裝飾器,需要的變數被閉包完美捕捉,邏輯也挺簡單明瞭。問的人說邏輯看著挺正常的,但就是一直報變數retry_times找不到(unresolved reference)的錯誤提示。

沒錯仔細捋一下,這是一道送分題呢:閉包捕獲的變數(retry_times,retry_wait)相當時引用的retry函式的區域性變數,當在wrapped_function的區域性作用於裡面操作不可變型別的資料時,會生成新的區域性變數,但是新生成的區域性變數retry_times在使用時還沒來得及初始化,因此會提示找不到變數;retry_wait相反能被好好的使用到。

python是duck-typing的程式語言,就算有warning照樣跑,寫個簡單到極限的的函式,用一下裝飾器,在wrapped_function邏輯裡打個斷點看一下各個變數的值也是很快能找到問題的(直接跑也能看到錯誤:unboundlocalerror: local variable 'retry_attempts' referenced before assignment, 至少比warning msg有用):

@retry(7, 8)

def test():

print 23333

raise exception('call me exception 2333.')

if __name__ == '__main__':

test()

output: unboundlocalerror: local variable 'retry_times' referenced before assignment

要解決這種問題也好辦,用乙個可變的容器把要用的不可變型別的資料報裝一下就行了(說個好久沒寫c#**記不太清楚完全不負責任的題外話,就像在c#.net裡面,碰到閉包的時候,會自動生成乙個混淆過名字的類然後把要**捉的值當作類的屬性存著,這樣在使用的時候就能輕鬆get,著名的老趙好像有一篇文章講lazy evaluation的好像涉及到這個話題):

def retry(attempts=3, wait=2):

temp_dict =

def retry_decorate(fn):

@wraps(fn)

def wrapped_function(*args, **kwargs):

print id(temp_dict), temp_dict

while 程式設計客棧temp_dict.get('retry_times') > 0:

try:

return fn(*args, **kwargs)

except :

sleep(temp_dict.get('retry_wait'))

temp_dict['retry_times'] = temp_dict.get('retry_times') - 1

print id(temp_dict), temp_dict

print id(temp_dict), temp_dict

return wrapped_function

return retry_decorate

@retry(7, 8)

def test():

print 23333

raise exception('call me exception 2333.')

if __name__ == '__main__':

test()

輸出:4405472064

4405472064

23333

4405472064

23333

4405472064

23333

4405472064

從output中可以看到,用dict包裝後,程式能夠正常的工作,和預期的一致,其實我們也可以從函式的閉包的值再次確認:

>>> test.func_closure[1].cell_contents

我是結尾,peace!

本文標題: 例項講解python的函式閉包使用中應注意的問題

本文位址: /jiaoben/python/153959.html

函式閉包python中的閉包

本文純屬個人見解,是對前面學習的總結,如有描述不正確的地方還請高手指正 單簡說,閉包就是根據不同的置配息信到得不同的結果 再來看看專業的解釋 閉包 closure 是詞法閉包 lexical closure 的簡稱,是引用了由自變數的函式。這個被引用的由自變數將和這個函式一起存在,即使已離開了造創它...

python閉包的例項詳解

1 在外部函式中定義內部函式,內部函式包含訪問外部函式。即使外部函式的生命週期結束後,內部函式仍然可以訪問外部函式變數。2 外部函式的返回值是內部函式本身。def outer cheer hello def inner name return cheer name return inner if n...

python閉包函式

python函式閉包 closure 比較抽象,在函式式程式設計中運用地比較多,通俗點就是子函式 內嵌函式 呼叫上層函式 閉包函式 的變數,且上層函式 閉包函式 接收的變數會儲存在子函式 內嵌函式 的變數中可以供子函式 內嵌函式 呼叫 概念很抽象,但是實現的例子還是比較容易理解的,這裡記住實現函式閉...