python 的装饰器,其实用到了以下几个语言特点:
- 1. 一切皆对象
- 2. 函数可以嵌套定义
- 3. 闭包,可以延长变量作用域
- 4. *args 和 **kwargs 可变参数
第1点,一切皆对象,包括函数。函数也是个对象,所以函数这个对象可以和其他任何对象一样被赋值给其它变量,包括作为实数传递给函数。
第2点,在函数中可以再定义一个函数,并且,结合第1点,函数是个对象,那么嵌套定义的函数,还可以被作为函数执行结果返回,也就是 return object。
第3点,类似 JS 的特性,就是在嵌套定义的函数销毁前,其外层函数的函数作用域一直存在。
第4点,则是为了处理参数上的方便。
普通装饰器
def decorator(func):
outer = '外层函数作用域定义的局部变量'
def inner(*args, **kwargs):
print outer
print args
print kwargs
return inner @decorator
def func(*args, **kwargs):
print 'hello world' # 以上装饰器作用等价于:
new_func = decorator(func) func(1, 2, 3, a='one', b='two')
new_func(1, 2, 3, a='one', b='two') # 外层函数作用域定义的局部变量
# (1, 2, 3)
# {'a': 'one', 'b': 'two'}
# 外层函数作用域定义的局部变量
# (1, 2, 3)
# {'a': 'one', 'b': 'two'}
带参数的装饰器
带参数的装饰器,其实是相当于又多了一层嵌套定义,装饰器函数返回的也是一个装饰器函数。
def decorator(info):
def really_dec(func):
outer = info
def inner(*args, **kwargs):
print outer
print args
print kwargs
return inner
return really_dec @decorator('我是装饰器参数')
def func(*args, **kwargs):
print 'hello world' func(1, 2, 3, a='one', b='two') # 我是装饰器参数
# (1, 2, 3)
# {'a': 'one', 'b': 'two'}