1、閉包linux
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.閉包的定義:(閉包 = 內部函數 + 定義環境時的變量)spa
若是在一個內部函數裏,對在外部做用域(非全局)的變量(外部環境變量能夠有不少)進行引用,那麼內部函數就被稱爲閉包(如上例)。閉包函數爲外部環境變量 在內部函數裏引用提供了途徑code
2、裝飾器blog
1.裝飾器的定義及舉例:作用域
舉例:get
假如咱們如今寫一個函數f():it
def f(): print('你是天才嗎')
可是後來客戶要求在調用f()函數的同時,要顯示執行f()函數花費的多長時間,而後咱們寫了以下的顯示函數:class
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()一個執行的參數,僅此而已