閉是封閉(函式中的函式),包是包含(該內部函式對外部函式作用域而非全域性作用域變數的引用。)
閉包:
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...