装饰器
关于装饰器我们先来了解了解什么是闭包
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
本质上就是多返回了一层装饰器而已