装饰器

关于装饰器我们先来了解了解什么是闭包

0X01

闭包概念

closure:内部函数中对enclosing作用域的变量进行引用

 

0X02

看段小Demo

def func(val):def in_func():
        print (val)
    in_func()
    return in_func

f = func(89)
f()

我们首先可以看到在func函数中定义了一个函数in_func,那么调用func函数返回in_func函数。

从C语言角度讲就是返回了一个函数指针,可是我们看看运行结果

89
89

f()函数的返回结果是89

func函数调用完成从C语言来角度来说调用栈清除,为什么f()函数还能89呢?

0X03

首先我们应该了解的是在Python中与C不同的是Python函数是一种对象

那么看看val与函数f()的地址

def func(val):
    print ('%x'%id(val))
    def in_func():
        print (val)
    in_func()
    return in_func

f = func(89)
f()
print (f.__closure__)

运行结果如下

2ff8598
89
89
(<cell at 0x03025650: int object at 0x02FF8598>,)

我们发现地址都是0X02FF8598! 

那么闭包实际就是内置函数把引用的变量放入了自己函数属性中进行返回

 

0X04


既然值可以作为函数属性与函数一起返回,那么函数也可以作为另函数属性返回

def dec(func):
    def in_dec(*arg):
        print 'In dec'
        if len(arg) == 0:
            return 0
        for val in arg:
            if not isinstance(val, int):
                return 0
        return func(*arg)
    return in_dec


def my_sum(*arg):
    return sum(arg)


my_sum = dec(my_sum)

print my_sum(1,2,3,4,5,6)

如上所示,其实装饰器也就是闭包的一种。

 

综上所述
1.装饰器用来装饰函数
2.返回一个函数对象
3.被装饰函数标识符指向返回的函数对象

 

0X05

无参数装饰器

def dec(func):
    def in_dec(*arg):
        print 'In dec'
        if len(arg) == 0:
            return 0
        for val in arg:
            if not isinstance(val, int):
                return 0
        return func(*arg)
    return in_dec


@dec #my_sum = dec(my_sum)
def my_sum(*arg):
    return sum(arg)

print my_sum(1,2,3,4,5,6)

 

对照上个闭包来看@dec的作用就是 执行了my_sum = dec

 

0X06

有参数装饰器

有参数装饰器相对于无参数装饰器来说就相当于多了一层嵌套

 

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()

我们把@log('DEBUG')进行展开

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

 

本质上就是多返回了一层装饰器而已

 

posted on 2016-06-22 16:00  zbility  阅读(386)  评论(0编辑  收藏  举报

导航