python基礎 閉包函式和裝飾器

2022-03-17 07:50:51 字數 4002 閱讀 4805

首先我們應該知道一件事:函式的定義域跟定義位置有關係,而跟呼叫位置沒有關係。

閉包函式:

定義:內層函式對外層函式而非全域性變數的引用,就叫做閉包函式

閉包會一直存在在記憶體中,不會因為函式執行結束而被釋放

先看個例子:

def

outer():

num = 1

definner():

nonlocal num

num += 1

print

(num)

return

inner

a = outer() #

此時a為乙個函式

a() #

2a() #

3a() #

4

num會一直存在,不會因為外層函式結束而釋放。

這就是閉包函式,可以在任何地方呼叫

閉包的意義

意義:返回的函式物件,不僅僅是乙個函式物件,在該函式外還包裹了一層作用域,

這使得無論在何處呼叫,優先使用自己外層包裹的作用域

裝飾器:閉包函式的一種應用場景

裝飾器原則:1,不修改物件的源**,2,不修改物件的呼叫方式,

目標:在遵循1,2的前提下,為被裝飾物件新增上新的功能

假如我們有這樣乙個需求,測試乙個函式所用的時間

import

time

deffunction():

time.sleep(1)

print('

函式執行')

start_time =time.time()

function()

end_time =time.time()

print("

函式的執行時間%s

" %(end_time -start_time))

#但此時多了幾行**,再次修改

deffunction():

time.sleep(1)

print('

函式執行')

deftimeer():

start_time =time.time()

function()

end_time =time.time()

print("

函式的執行時間%s

" % (end_time -start_time))

timeer()

#我們要想也計算其他函式的時間怎麼辦?

deffunction1():

time.sleep(1)

print('

函式執行')

deftimeer(function):

start_time =time.time()

function()

end_time =time.time()

print("

函式的執行時間%s

" % (end_time -start_time))

timeer(function1)

#又有了新的要求,我們想要在不改變原函式的呼叫方式來修改

#可以用閉包來實現

deffunction2():

time.sleep(1)

print('

函式執行')

deftimeer(function):

definner():

start_time =time.time()

function()

end_time =time.time()

print("

函式的執行時間%s

" % (end_time -start_time))

return

inner

function2 =timeer(function2)

function2()

#這樣就可以在不修改函式呼叫方式的情況下增加功能

#python有乙個語法糖的功能,例子如下

deftimeer(function):

definner():

start_time =time.time()

function()

end_time =time.time()

print("

函式的執行時間%s

" % (end_time -start_time))

return

inner

@timeer

#相當於:function2 = timeer(function2)

deffunction2():

time.sleep(1)

print('

函式執行')

function2()

上述就是裝飾器的基本方式

新的問題又來了,我們寫的函式有引數怎麼辦呢?

我們直接給inner加上引數就好了啊

注意,此時引數應該怎麼加,應該保證同時適用於有引數和無引數的函式

因為我們不知道函式有幾個引數,所以應該用不定長引數

def

timeer(function):

def inner(*args,**kwargs):

#這樣函式沒有引數也可以用

start_time =time.time()

function(*args,**kwargs)

end_time =time.time()

print("

函式的執行時間%s

" % (end_time -start_time))

return

inner

@timeer

deffunction2():

time.sleep(1)

print('

函式執行')

@timeer

defadd_num(num1,num2):

print(num1 +num2)

function2()

add_num(3,5)

不知道大家發現沒有,我們還有乙個問題沒有解決,

對了,那就是函式的返回值的問題,我們怎麼給有返回值的函式加裝飾器呢?

我們從前面可以知道,我們加了裝飾器,是會執行裝飾器內部的inner函式

那麼我們給inner函式加上返回值就好了啊,看**:

def

timeer(function):

def inner(*args,**kwargs):

#這樣函式沒有引數也可以用

start_time =time.time()

res = function(*args,**kwargs)

#此處用乙個變數來接受函式的返回值。

end_time =time.time()

print("

函式的執行時間%s

" % (end_time -start_time))

#函式的最後應該有返回值,而且這個返回值必須是function函式執行後的返回值,

#那麼我們就知道該怎麼寫**了,我們用乙個變數來接受函式function執行後的返回值就好了啊

return

res

#在此處返回

return

inner

@timeer

defmax_num(num1,num2):

if num1 >num2:

return

num1

else

:

return

num2

print(max_num(3,5))

def

outer(function):

def inner(*args,**kwargs):

#函式執行前你想要做的

res =function()

#函式執行後你想要做的

return

res

return inner

那麼到此處我們就已經掌握了裝飾器的內容,上邊是乙個框架

python基礎之閉包函式和裝飾器

補充 全域性變數宣告及區域性變數引用 python引用變數的順序 當前作用域區域性變數 外層作用域變數 當前模組中的全域性變數 python內建變數 global關鍵字用來在函式或其他區域性作用域中使用全域性變數,宣告後可以在其他作用於中修改和使用 x 1 全域性賦值變數 def foo globa...

python裝飾器,閉包函式

閉包函式 在函式a內部定義另外乙個函式b,之後b作為a的返回值直接被返回。此時函式b稱為a的閉包函式。在閉包函式b中如果使用a函式中定義的變數,此時a函式中被定義的變數會被臨時儲存,直到b函式呼叫結束時該變數才會被系統收回,從而實現a中變數延遲釋放 例如global 宣告的變數屬於全域性變數,此時在...

函式裝飾器和閉包

裝飾器是可呼叫的物件,其引數是另乙個函式 被裝飾的函式 裝飾器可能會處理被裝飾的函式,然後把它返回,或者將其替換成另乙個函式或可呼叫物件。裝飾器通常把函式替換成另乙個函式 defdeco func definner print running inner return inner deco def ...