python內部函數、閉包共同之處在於都是以函數作為參數傳遞到函數,不同之處在於返回與調用有所區別。
1、python內部函數
python內部函數示例:
def test(*args):
def add(*args): # 顯示的調用外部函數的參數
return args
return add(*args) # 返回內部函數的直接調用
運行結果如下:
test(1,2,3)
(1,2,3)
內部函數直接引用外部函數參數,外部函數test顯示的返回內部函數add的調用。
當需要在函數內部多次執行復雜任務時,內部函數非常有用,從而避免了循環和代碼的堆疊重復。
2、python閉包
內部函數可以看作是一個閉包。閉包是一個可以由另一個函數動態生成的函數,並且可以改變和存儲函數外創建的變量的值。
python閉包示例:
def test(a):
def add(): # 沒用引用外部函數的參數
return "it's a callable %s" % a # 直接在內部函數使用外部函數的參數
return add # 返回內部函數本身,不返回內部函數調用
運行結果如下:
a1 = test(1) # 動態生成的一個可以記錄外部變量的函數
<function __main__.add>
a1() # 調用此函數
it's a callable 1
test(1)() # 本身調用過程,先動態生成一個函數再進行調用
it's a callable 1
3、python裝飾器
裝飾器實質上是一個函數,它把一個函數作為輸入並且返回另外一個函數,在裝飾器中,通常使用下面這些python技巧:
-
*args 和 **kwargs
-
閉包
-
作為參數的函數
python裝飾器示例:
def test(func): # 將函數作為參數進行傳遞
def add(*args,**kwargs):
print “it's a d”
return func(*args,**kwargs) # 內部函數進行相關操作以后,返回傳遞函數的調用
return add
def func(a,b):
return a+b
運行結果如下:
test(func) # 將func作為函數傳遞進test函數進行裝飾
<function __main__.add> # 裝飾后的函數,類似閉包
test(func)(1,2) # 顯示的對裝飾后的函數進行調用
it's a d # 中間被裝飾的過程被print出來
3
更簡單的方法調用裝飾器
@test # 同一個函數可以調用多個裝飾器,執行過程中不分先后順序
def func(a,b):
return a+b
無論傳入test()的函數func是什么,裝飾器都會返回一個新的函數,其中包含test增加的額外語句。
實際上,裝飾器並不需要執行函數func中的代碼,只是在結束前函數add調用函數func以得到的func返回的結果和附加代碼的結果
裝飾器本身需要傳遞參數的時候:
def test(cmd): # 將參數傳遞
def exc(func): # 第二步進行函數作為參數傳遞
def add(*args,**kwargs):
print "it's a %s" % cmd
print "begin"
return func(*args,**kwargs)
return add
return exc
運行結果如下:
test('haha')
<function __main__.exc>
test('haha')(func)(1,2) # 調用裝飾器返回結果
it's a haha
begin
3
更簡單的方法調用
@test('haha') # test函數進行了參數傳遞
def func(a,b):
return a+b
python裝飾器注意事項:
對func進行裝飾以后,func的函數命名空間發生了變化
執行 func.__name__ add
如何指向原來的命名空間呢?python自帶了functools庫直接調用則行
import functools
def test(func):
@functools.wraps(func)
def add(*args,**kwargs):
print "it's a decorator"
return func(*args,**kwargs)
return add
@test
def func(a,b):
return a+b
再次運行,查看命名空間
func.__name__
func # 返回了本身
