您的位置:首页 > 编程语言 > Python开发

Python学习笔记(六):decorator装饰器

2015-06-15 22:23 603 查看

一、装饰器的用途和作用

装饰器,一种高阶函数的表达方法,传入函数,返回函数。

将需要完善的函数作为参数 传入高阶函数,在高阶函数内,调用这个函数,并返回一个函数名,代替待完善函数。



用途:已经定义了函数,想动态改变函数功能,又不想改变原函数的代码时,可以使用装饰器。

装饰器作用:

可以极大地简化代码,避免每个函数编写重复性代码

.Python内置的@语法就是为了简化装饰器调用;

打印日志:@log

检测性能:@performance

数据库事务:@transaction

URL路由:@post('/register')

二、无参数的decorator

要让
@log 自适应任何参数定义的函数,可以利用Python的 *args 和 **kw,保证任意个数的参数总是能正常调用:

*args可以当作可容纳多个变量组成的tuple

**kw可以当作容纳多个key和value的dict

同时使用*args和**kws时,必须*args参数列要在**kw前

栗子:计算函数调用的时间可以记录调用前后的当前时间戳,然后计算两个时间戳的差。

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)


三、带参数的decorator

带参数的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()


四、完善decorator

由于decorator返回的新函数函数名已经不是原函数,而是@log内部定义的。这对于那些依赖原函数名的代码就会失效。decorator还改变了函数的__doc__等其它属性。如果要让调用者看不出一个函数经过了@decorator的“改造”
,就需要把原函数的一些属性复制到新函数中。

Python内置的functools可以用来自动化完成这个“复制”的任务,@functools.wraps应该作用在返回的新函数上。

最后需要指出,由于我们把原函数签名改成了(*args, **kw),因此,无法获得原函数的原始参数信息。即便我们采用固定参数来装饰只有一个参数的函数。

栗子:

import functools
def log(f):
    @functools.wraps(f)
    def wrapper(*args, **kw):
        print 'call...'
        return f(*args, **kw)
    return wrapper


五、偏函数

当一个函数有很多参数时,调用者就需要提供多个参数。如果减少参数个数,就可以简化调用者的负担。

functools.partial可以把一个参数多的函数变成一个参数少的新函数,少的参数需要在创建时指定默认值,这样,新函数调用的难度就降低了。

>>> import functools

>>> int2 = functools.partial(int, base=2)

>>> int2('1000000')

64

>>> int2('1010101')

85
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: