閉包 裝飾器

2021-09-25 17:24:06 字數 3506 閱讀 8284

閉是封閉(函式中的函式),包是包含(該內部函式對外部函式作用域而非全域性作用域變數的引用。)

閉包:

def

foo():

print

("in foo()"

)def

bar():

print

("in bar()"

)#1. 直接執行內部函式報錯

# bar()

# # 2.先執行外部函式,再執行內部函式,依然會報錯

# foo()

# bar()

由於作用域的問題,函式內的屬性都是有生命週期的,只有在函式執行期間

在這段**,只有呼叫foo()是,內部的print()及bar()才能存活。

現在我們為了讓foo()內bar()存活,就是呼叫bar()

def

foo():

print

("in foo()"

)def

bar():

print

("in bar()"

)return bar

var = foo(

)var(

)

內部函式對外部函式作用域的引用

—>引數呼叫

def

foo():

a =66print

("in foo()"

)def

bar(num)

:print

("in bar()"

)print

(a + num )

return bar

var = foo(

)var(22)

# in foo()

# in bar()

# 88

li =[1

,2,3

,4,5

]def

foo(obj)

:print

("foo"

,obj)

defbar()

: obj[0]

+=1print

("bar"

,obj)

return bar

# 程式在執行時,foo()函式返回給了內部定義的bar()函式

var = foo(li)

# 將返回值賦值給var

var(

)var(

)var(

)# foo [1, 2, 3, 4, 5]

# bar [2, 2, 3, 4, 5]

# bar [3, 2, 3, 4, 5]

# bar [4, 2, 3, 4, 5]

@func1

deffunc()

:print

('aaa'

)

裝飾器存在的意義

一般常見的,比如拿到第三方api介面,第三方不允許修改這個介面,需要使用裝飾器。

裝飾器本身是乙個函式,作用是為現有存在的函式,在不改變函式的基礎上,新增一些功能進行裝飾。

它是以閉包的形式實現的。

在使用裝飾器函式時,在被裝飾的函式的前一行,使用@裝飾器函式名形式來進行裝飾。

demo:

現在在乙個專案中,有很多函式,由於我們的專案越來越大,功能也越來越多,導致程式越來越慢。

其中乙個功能函式的功能,是實現一百萬次的累加。

def

my_count()

: s =

0for i in

range

(1000001):

s += i

print

("sum: "

,s)

計算時間

import time

defmy_count()

: s =

0for i in

range

(1000001):

s += i

print

("sum: "

,s)start = time.time(

)my_count(

)end = time.time(

)print

("執行時間為:"

,(end - start)

)# sum: 500000500000

# 執行時間為: 0.0608363151550293

每乙個函式都進行時間計算,此方式比較麻煩,**過於多餘。

import time

defmy_count()

: s =

0for i in

range

(1000001):

s += i

print

("sum: "

,s)def

count_time

(func)

: start = time.time(

) func(

) end = time.time(

)print

("執行時間為:"

,(end - start)

)count_time(my_count)

# 仍然更改了呼叫方式

# sum: 500000500000

# 執行時間為: 0.054853200912475586

修改之後,定義乙個函式來實現時間計算功能。

使用時需要將對應的函式傳入到時間計算函式中。

但是啟用時間計算功能時更改了my_count的函式呼叫方式。

import time

defcount_time

(func)

:def()

: start = time.time(

) func(

) end = time.time(

)print

("執行時間為:"

,(end - start)

)@count_time

defmy_count()

: s =

0for i in

range

(1000001):

s += i

print

("sum: "

,s)

my_count(

)

這樣實現的好處,定義閉包函式後,只需要通過@裝飾器函式名形式的裝飾器語法,就可以將@裝飾器函式名加到要裝飾的函式前即可

這種不改變原有函式功能,對函式進行拓展的形式,就稱為裝飾器

在執行@裝飾器函式名時,就是將原函式傳遞到閉包中。然後,原函式的引用指向閉包返回的裝飾過的內部函式的引用。

閉包 裝飾器

外部函式返回內部函式的引用 內部函式可以直接使用外部函式的環境變數 語法 外部函式通過返回內部函式的引用 內部函式可以直接使用外部函式的 環境變數 自由變數 函式執行時間統計 執行函式前預備處理 執行函式後清理功能 許可權校驗等場景 快取有且只有乙個引數 指向了被裝飾的函式的引用 使用裝飾器 裝飾器...

閉包,裝飾器

多層函式巢狀,函式裡面還有定義函式,一般是兩個 往往內層函式會用到外層函式的變數,把內層函式以及外部函式的變數當成乙個特殊的物件,這就是閉包。閉包比物件導向更純淨 更輕量,既有資料又有執行資料的 比普通函式功能更強大,不僅有 還有資料 利用閉包的基本原理,對乙個目標函式進行裝飾,即在執行乙個目標函式...

閉包 裝飾器

定義乙個函式 def test number 在函式內部再定義乙個函式,並且這個函式用到了外邊函式的變數,那麼將這個函式及用到的一些變數稱之為閉包 def test in number in print in text in 函式,number in is d number in return nu...