python 裝飾器、內部函數、閉包簡單理解

python內部函數、閉包共同之處在於都是以函數做爲參數傳遞到函數,不一樣之處在於返回與調用有所區別。python

一、python內部函數

python內部函數示例:閉包

def test(*args):
    def add(*args):         #  顯示的調用外部函數的參數
        return args
    return add(*args)       #  返回內部函數的直接調用

運行結果以下:
test(1,2,3)
(1,2,3)    

 
內部函數直接引用外部函數參數,外部函數test顯示的返回內部函數add的調用。
當須要在函數內部屢次執行復雜任務時,內部函數很是有用,從而避免了循環和代碼的堆疊重複。函數

 

二、python閉包

內部函數能夠看做是一個閉包。閉包是一個能夠由另外一個函數動態生成的函數,而且能夠改變和存儲函數外建立的變量的值。blog


python閉包示例:
cmd

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

 

三、python裝飾器

裝飾器實質上是一個函數,它把一個函數做爲輸入而且返回另一個函數,在裝飾器中,一般使用下面這些python技巧:it

  • *args 和 **kwargsio

  • 閉包function

  • 做爲參數的函數class

python裝飾器示例:test

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                  # 返回了自己
相關文章
相關標籤/搜索