Python裝飾器

經過咱們的python柯里化就能學習裝飾器啦~!
python

裝飾器應該是目前來講學到的比較困難的,很是很是重要,下面根據代碼演化出裝飾器
ide


需求:
函數

  一個加法函數,想加強它的功能,可以輸出被調用過以及調用的參數信息學習

def add(x, y, file):
    print("call {}, {} + {}".format(add.__name__, x, y), file=file)
    """"
    __name__是一個特殊的屬性,將日誌輸出到控制檯
    print函數後面其實還能夠跟file,將輸出信息輸出到其它地方,好比d:/123
    """
    return x + y
print(add(4, 5))

上面的加法函數是完成了需求,可是有如下的缺點:
spa

  打印語句的耦合過高;日誌

  加法函數屬於業務功能,而輸出信息的功能,屬於非業務功能代碼,不應放在業務函數加法中;orm

  這種寫法有種稱呼叫作侵入式代碼;it

想一下想要對函數的功能進行加強怎麼辦呢?如何作到業務功能離?io

def add(x, y):
    return x + y

def logger(function):
    print('-------begin-----')# 加強的輸出
    x = function(4, 5)# 至關於x = add(4, 5)
    print('------end--------')# 加強的功能
    return x

print(logger(add))

上面代碼作到了業務功能分離,可是x = function(4, 5)這裏會有問題,這裏被寫死了?該如何作呢?
function

def add(x, y):
    return x + y

def logger(function, x, y):
    print('-------begin-----')
    x = function(x, y)
    print('------end--------')
    return x

print(logger(add))

這樣能作到,可是仍是有問題,若是個人函數是這樣寫的,怎麼辦?

def add1(x, y):
    return x + y

def add2(x, y, z):
    return x + y + z

def logger(function, x, y):# x, y這裏寫死確定不行啦
    print('-------begin-----')
    x = function(x, y)
    print('------end--------')
    return x

print(logger(add1))
print(logger(add2)) ####

怎麼搞定呢?

def add1(x, y):
    return x + y

def add2(x, y, z):
    return x + y + z

def add3(x, y, *args, z):
    return x + y + z

def logger(function, *args, **kwargs):
    print('-------begin-----')
    x = function(*args, **kwargs)
    print('------end--------')
    return x

print(logger(add1, 4, 5))
print(logger(add2, 4, 5, 6))
print(logger(add3, 4, z=5, y=6))

試想還能不能在變化一下?(柯里化)

def add1(x, y):
    return x + y

def add2(x, y, z):
    return x + y + z

def add3(x, y, *args, z):
    return x + y + z

def logger(function):
    def _logger(*args, **kwargs):
        print('-------begin-----')
        x = function(*args, **kwargs)
        print('------end--------')
        return x
    return _logger

foo = logger(add1)
print(foo(10, 20))

若是把foo = logger(add1)換成add1 = logger(add1),這樣會不會報錯?

不會報錯,那麼就有更簡單的方式了———裝飾器

def logger(function):
    def _logger(*args, **kwargs):
        print('-------begin-----')
        x = function(*args, **kwargs)
        print('------end--------')
        return x
    return _logger

@logger # 這句至關於 add1 = logger(add1)
def add1(x, y):
    return x + y

print(add1(4, 5))

這就是裝飾器函數.

@logger這句是語法糖,至關於add1 = logger(add1),因此當最後一句print(add1(4,5)),這裏調用的add1至關於調用的是logger函數

的內層函數,跟def add1(x, y)這句沒有關係了

這就是裝飾器的演化,可是前面幾個技術須要熟悉掌握,好比傳參,解構的技巧

注意規範:

  外層函數要返回內層函數的引用;

  外層函數至少傳入一個參數,這個參數應該是要被包裝的一個函數;

  既然是包裝原函數,就不能被改造;

相關文章
相關標籤/搜索