python 装饰器

装饰器是设计模式的一种,在面向对象中可以实现动态的给对象添加功能,通常使用对象组合的方式来实现。

如现在有个类A有个操作operation定义如下:

class A:
    def operation(self):
        print 'sonme operation'

我们需要对A的操作进行装饰,希望在operation前后做一些装饰操作,所以我们实现如下装饰类:

class Decrator:
    def __init__(self, obj):
        self.obj = obj

    def operation(self):
        print 'do something before operation'
        self.obj.operation()
        print 'do something after operation'

python中的装饰器类似上面功能,目的是在不影响原有实现的基础上,在调用原来实现之前或者之后增加一层逻辑,比如说鉴权、缓存、超时设置、统计监控等。

装饰器也是函数,它可以用来装饰其它函数,所以是一个嵌套函数的结构。

def outter(a):
    def inner(b):
        return a + b

    return inner

o = outter(112)
print o(23)
以下是最简单的一个python装饰器的实现:

def decorator(fn):
    fn.cnt = 0
    def warpper(x):
        fn.cnt += 1
        print fn.cnt
        return fn(x)

    return warpper
 
@decorator
def action(x):  
    return x*x  
 
action(3)
action(3)  
action(3)
以上输出为:

1

2

3
装饰器函数默认参数为被装饰的函数,在代码被加载时就执行

如上,加载装饰器后action对应的定义已经改变,类似于:

raw_action = action
action = decorator(raw_action)

以上的装饰器函数装饰时没有传递参数,默认参数就是被装饰函数,但有时候我们也需要对装饰函数传递一些参数,如缓存的时间

def cache(timeout):
    def decorator(func):
        def wrapper(*args):
            if timeout > 10:
                return func(*args)
            else:
                print 'get value from cache'
                return 'cache value'

        return wrapper

    return decorator

@cache(10)
def test(x, y):
    return x*y

test(12, 12)

以上输出为:

get value from cache

由于有参数的装饰函数在调用时只会使用应用时的参数 而不接收被装饰的函数做为参数,所以必须在其内部再创建一个函数用来接收被装饰函数作为参数

这时的test定义类似于:

raw_test = test
test = cache(10)(raw_test)

当然,装饰器也可以组合使用,多个装饰器来装饰一个函数

def decorator(fn):
    fn.cnt = 0
    def wrapper(x):
        fn.cnt += 1
        print fn.cnt
        return fn(x)

    return wrapper

def decorator2(fn):
    def wrapper(*args):
        print 'another decorator2'
        return fn(*args)

    return wrapper
 
@decorator
@decorator2
def action(x):  
    return x*x
装饰的顺序为由近及远,即离被装饰函数最近的装饰器开始自底向上执行装饰

raw_action = action
action = decorator2(raw_action)
action = decorator(action)



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值