一、閉包
1.舉例
defouter():
x= 10
def inner(): #內部函數
print(x) #外部函數的一個變量
returninner#調用inner()函數的方法
outer()() #法一
f=outer()
f()#法二
注意:inner()是局部變量,在全局范圍不可調用(即不能直接調用inner()函數),但是在法二中,在執行完 f=outer() 之后,outer()函數就已經結束,執行f()的時候卻可以調用inner()函數,并輸出x的值,這是因為outer()里 return 的 inner是一個閉包函數,里面有x這個環境變量
2.閉包的定義:(閉包 = 內部函數 + 定義環境時的變量)
如果在一個內部函數里,對在外部作用域(非全局)的變量(外部環境變量可以有很多)進行引用,那么內部函數就被稱為閉包(如上例)。閉包函數為外部環境變量在內部函數里引用提供了途徑
二、裝飾器
1.裝飾器的定義及舉例:
舉例:
假如我們現在寫一個函數f():
deff():print('你是天才嗎')
但是后來客戶要求在調用f()函數的同時,要顯示執行f()函數花費的多長時間,然后我們寫了如下的顯示函數:
importtimedefshow_time():
start= time.time() #顯示計算機此刻的時間(不是傳統的時間,而是linux自誕生至今所經過的時間)
f()
time.sleep(1) #執行完f()之后停留一秒再執行下面的語句,因為f()的執行時間太短顯示不出
end =time.time()print("spend %s" % (end -start))deff():print('你是天才嗎')
show_time()
我們通過執行show_time() 執行了f()函數,并且返回了執行f()函數所花費的時間,但是卻改變了調用方式,以前是直接調用f(),現在是調用show_time() ,這樣做對于應用 此函數的人員影響很大,因為他們要把所有用f()函數的都改過來,而且如果要計算其他函數的執行時間,就要修改show_time()函數內部或者另外寫一個函數,代碼的重復率高,所以我們再做一個改進:
importtimedefshow_time(func):definner(): #定義一個外部函數
start= time.time() #顯示計算機此刻的時間(不是傳統的時間,而是linux自誕生至今所經過的時間)
func()
time.sleep(1) #執行完f()之后停留一秒再執行下面的語句,因為f()的執行時間太短顯示不出
end =time.time()print("spend %s" % (end -start))returninnerdeff():print('你是天才嗎')
f=show_time(f) #此后我們不管需要那個函數的執行時間,只需要把 f 修改為對應的函數名即可
f()
對于 f=show_time(f)? 還有一種寫法:
importtimedefshow_time(func):def inner(): #定義一個外部函數
start = time.time() # 顯示計算機此刻的時間(不是傳統的時間,而是linux自誕生至今所經過的時間)
func()
time.sleep(1) #執行完f()之后停留一秒再執行下面的語句,因為f()的執行時間太短顯示不出
end =time.time()print("spend %s" % (end -start))returninner
@show_time#相當于 f = show_time(f)
deff():print('你是天才嗎')
f()
定義:函數show_time() 就是一個裝飾器,它把真正的方法func包在了函數里面,看起來像func()被上下的時間函數裝飾了,? @符號是裝飾器的語法,在定義函數的時候使用,避免再一次賦值
當程序運行時先執行@show_time,@show_time 幫我們做的就是當執行f() 時,執行的代碼從黃框轉向紅框部分,相當于給了inner()一個執行的參數,僅此而已