decorator
前提:everything in python is object even function,attributes,variables,params
看这篇之前请先看closure:python简单进阶,closure
两个有趣的例子
def inc(x):
return x + 1
def dec(x):
return x - 1
# 传进一个方法,和一个参数
# 返回这个方法
def operation(func, x):
return func(x)
print(operation(inc, 1))
执行结果
2
# 可以看作 closure,只不过保存的参数是方法
# 其实就是closure,只不过保存的参数是方法
def make_pretty(func):
def inner():
print("I got decorated")
func()
return inner
def ordinary():
print("I am ordinary")
pretty = make_pretty(ordinary)
pretty()
print(pretty.__closure__[0].cell_contents)
执行结果
I got decorated
I am ordinary
<function ordinary at 0x000000001BD854A8>
另外一种写法
add the @make_pretty to ordinary() is same to ordinary = make_pretty(ordinary)
def smart_divide(func):
def inner(a, b):
print("I am going to divide ", a, "and", b)
if (b == 0):
print("Whoops! cannot divide")
return
return func(a, b)
return inner
@smart_divide
def divide(a, b):
return a / b
print(divide(1, 2))
print(divide(1, 0))
看上面的形式可以总结出,能够给别的函数作为修饰器用的必须有如下的特性
- 作为修饰器的函数内部必须有一个
inner()
函数,且最终要返回inner
- 作为修饰器的函数内部
inner()
函数的参数个数必须和被修饰的函数接收的参数数目一直 - 修饰器函数必须接受一个参数,这个参数就是被修饰的方法
遵守如上写法,我们就能写一个修饰器
写一个能修饰任何方法的修饰器
def walk_for_all(func):
def inner(*args, **kwargs):
print "包装"
print func(*args, **kwargs)
print "包装"
return inner
修饰器可以多个同时修饰
def father_protect(func):
def inner(*args, **kwargs):
print("F" * 30)
func(*args, **kwargs)
print("F" * 30)
return inner
def mother_protect(func):
def inner(*args, **kwargs):
print("M" * 30)
func(*args, **kwargs)
print("M" * 30)
return inner
@father_protect
@mother_protect
def child(msg):
print(msg)
child("I am save")
执行结果
FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
MMMMMMMMMMMMMMMMMMMMMMMMMMMMMM
I am save
MMMMMMMMMMMMMMMMMMMMMMMMMMMMMM
FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
上面的例子都是我仔细写的,如果认真看完的话,应该会对decorator有比较好的理解。