[詳細資料](http://www.bjhee.com/python-decorator.html)
基本上,函數可以當作傳遞對象的,都有閉包的概念
就是能夠在函數中回傳內部的函數
這樣在外部函數生命週期結束後,內部函數的資源還可以使用
閉包主要有兩個功能
1.隱藏要使用的物件,只有內部函數可調用,上面有提到
2.將擁有類似功能的函數定義好,由傳入的參數來區別差異的部分
# 例:
def multiply(number):
    def in_func(value):
        return value * number
    return in_func

# 有了multiply這個閉包,就不需要額外定義double和triple函數
double = multiply(2)
triple = multiply(3)
print(double(5))
print(triple(3))
# 當multiply函數生命週期結束後,仍然可以在in_func.__closure__找到number變數
# 之後當使用double函數時需要用到number,就會從double.__closure__找到number
# 上面範例是透過傳入數值,這次如果傳入函數物件呢
# 這邊使用logging package
# 這樣就不需要每個函數都加入logger
import logging
LOG_FILE = "test.log"
logging.basicConfig(filename = LOG_FILE, level = logging.DEBUG)
logger = logging.getLogger(__name__)

def add_log(func):
    def newFunc(): # 這個可以看成修飾原本function
        logger.debug("Before {} call".format(func.__name__))
        func()
        logger.debug("After {} call".format(func.__name__))
    return newFunc

def funcA():
    print("In funcA")

def funcB():
    print("In funcB")

newFuncA = add_log(funcA)
newFuncB = add_log(funcB)
newFuncA()
newFuncB()
# 上面的範例通用性比較低,因為它只能對沒有參數和沒有回傳值的函數生效
# 這更改就可以讓所有函數都適用這個閉包了
def add_log(func):
    def newFunc(*args, **kwargs): # *args能符合所有的position arguments,**kwargs可以符合所有key-value arguments
        logger.debug("Before %s() call" % func.__name__)
        res = func(*args, **kwargs)
        logger.debug("After %s() call" % func.__name__)
        return res # 回傳值
    return newFunc

def funcC(x, y):
    print x + y
newFuncC = add_log(funcC)
newFuncC(2, y=3)

results matching ""

    No results matching ""