装饰器
decorator 装饰器

def f1(x):
return x*2
def new_fn(f):
def fn(x):
print 'call ' + f.name + '()'
return f(x)
return fn
g1 = new_fn(f1)
print g1(5)

python内置的@语法就是为了简化装饰器调用
@new_fn
def f1(x):
return x*2
print(f1(5))

装饰器的作用
可以极大的简化代码,避免每个函数编写重复性代码,
打印日志:@log,
检测性能:@performance
数据库事务:@transaction
url路由:@post('/register')

编写无参数decorator
Python的 decorator 本质上就是一个高阶函数,它接收一个函数作为参数,然后,返回一个新函数。使用 decorator 用Python提供的 @ 语法,这样可以避免手动编写 f = decorate(f) 这样的代码。

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

编写无参数decorator
计算函数调用的时间可以记录调用前后的当前时间戳,然后计算两个时间戳的差。

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: xy, range(1, n+1))
print factorial(10)

编写带参数decorator

import time
def performance(unit):
    def perf_decorator(f):
        def wrapper(*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 wrapper
    return perf_decorator
@performance('ms')
def factorial(n):
    return reduce(lambda x,y: x*y, range(1, n+1))
print factorial(10)

完善decorator

import time, functools
def performance(unit):
    def perf_decorator(f):
        @functools.wraps(f)
        def wrapper(*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 wrapper
    return perf_decorator
@performance('ms')
def factorial(n):
    return reduce(lambda x,y: x*y, range(1, n+1))
print factorial.name

偏函数
实现忽略大小写排序 要固定sorted()的cmp参数,需要传入一个排序函数作为cmp的默认值。
import functools
sorted_ignore_case = functools.partial(sorted, cmp=lambda s1, s2: cmp(s1.upper(), s2.upper()))
print sorted_ignore_case(['bob', 'about', 'Zoo', 'Credit'])