【python基礎學習】基礎重點難點知識彙總

python中decorator裝飾器

語法示例:

@decorator

什麼是裝飾器:python

問題:
定義一個函數後
在運行時動態增長功能
又不想改動函數自己的代碼

示例:數據庫

# 但願對下列函數調用增長log功能,打印出函數調用:
def f1(x):
    return x*2
def f2(x):
    return x*x
def f3(x):
    return x*x*x

方法1:直接修改原函數的定義app

def f1(x):
    print('call f1')
    return x*2
def f2(x):
    print('call f2')
    return x*x
def f3(x):
    print('call f3')
    return x*x*x

有沒有更簡單的方法?函數

高階函數
1. 能夠接受函數做爲參數
2. 能夠返回函數
是否能夠接受一個函數,對其進行包裝,而後返回一個新函數?

方法2:經過高階函數返回新函數(裝飾器函數):post

def f1(x):
    return x*2
def new_fn(f):
    def fn(x):
        print('call'+f.__name__+'()')
        return f(x)
    return fn

調用1:性能

g1 = new_fn(f1)
print( g1(5) )

調用2:spa

f1 = new_fn(f1)
print( f1(5) )

裝飾器:

python內置@語法就是爲了簡化裝飾器調用翻譯

@new_fn
def f1(x):
    return x*2

等同於:日誌

def f1(x):
    return x*2
f1 = new_fn(f1)

裝飾器的做用:

能夠極大簡化代碼,避免每一個函數編寫重複性的代碼
    打印日誌:@log
    檢測性能:@performance
    數據庫事務:@transaction
    URL路由:@post('/register')

裝飾器示例:

1. 若是自定義函數存在兩個形參,上述裝飾器函數內部固定寫了一個形參,會出現錯誤怎麼辦:code

@new_fn
def add(x,y):
    return x+y
# 這裏會出現錯誤,因此須要更改 new_fn 函數以下:
def new_fn(f):
    def fn(*args, **kwargs):
        print('call'+f.__name__+'()')
        return f(*args, **kwargs)
    return fn

2. 請編寫一個@performance,它能夠打印出函數調用的時間。計算函數調用的時間能夠記錄調用先後的當前時間戳,而後計算兩個時間戳的差。

import time
def performance(f):
    def fn(*args, **kw):
        t1 = time.time()
        r = f(*args, **kw)
        t2 = time.time()
        print 'call %s() in %fs' % (f.__name__, (t2 - t1))
        return r
    return fn

@performance
def factorial(n):
    return reduce(lambda x,y: x*y, range(1, n+1))
print factorial(10)

3.上述裝飾器函數只能接受一個函數參數,若是裝飾器函數須要傳入額外的參數怎麼辦?

@log('DEBUG')
def my_func():
    pass

把上面的定義翻譯成高階函數的調用,就是:

my_func = log('DEBUG')(my_func)

上面的語句看上去仍是比較繞,再展開一下:

log_decorator = log('DEBUG')
my_func = log_decorator(my_func)

上面的語句又至關於:

log_decorator = log('DEBUG')
@log_decorator
def my_func():
    pass

因此,帶參數的log函數首先返回一個decorator函數,再讓這個decorator函數接收my_func並返回新函數:

def log(prefix):
    def log_decorator(f):
        def wrapper(*args, **kw):
            print '[%s] %s()...' % (prefix, f.__name__)
            return f(*args, **kw)
        return wrapper
    return log_decorator

@log('DEBUG')
def test():
    pass
print test()

上述第二個例子:@performance只能打印秒,請給 @performace 增長一個參數,容許傳入's'或'ms':

import time
import functools
def performance(unit):
    def perf_decorator(f):
        @functools.wraps(f)
        def wapper(*args, **kw):
            t1 = time.time()
            r = f(*args, **kw)
            t2 = time.time()
            t = (t2 - t1) * 1000 if unit=='ms' else (t2 - t1)
            print 'call %s() in %f %s' % (f.__name__, t,unit)
            return r
        return wapper
    return perf_decorator

@performance('ms')
def factorial(n):
    return reduce(lambda x,y: x*y, range(1, n+1))
print factorial(10)
print factorial.__name__

 

完善的裝飾器寫法:

相關文章
相關標籤/搜索