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