函数内部可以定义函数,且函数本身还可以返回函数。装饰器模式是实现面向切面编程 Aspect Oriented Programming ( AOP ) 的一种有效手段之一。
Python 的装饰器本身是一个函数。下面是一个简单的实例:
def before(ff):
print("before")
return ff
@before
def f(): print("f")
f() # before, f
函数 f()
被 before()
函数修饰。当调用 f()
函数时,该函数会被传入到 before()
函数内部。根据 before
的逻辑,它会首先执行一些前置操作,然后再将被拦截的操作 ff
( 即被装饰的函数 f
) 返回并执行,以此实现前置操作,比如,在这里插入统一的日志记录逻辑。
进一步,如何实现对目标函数的环绕操作呢?下文通过声明嵌套函数 ( 或称闭包 ) 的方式来实现。
def around(ff):
def wrap():
print("before")
ff()
print("after")
return wrap
@around
def f(): print("f")
f() # before, f, after
再进一步,考虑到目标函数也是有参数和返回值的。因此,我们在 wrap
闭包内设置 *args
和 **kwargs
参数传递到目标函数内。
def around(ff):
def wrap(*args, **kwargs):
print("before")
r = ff(*args, **kwargs)
print("after")
return r
return wrap
@around
def f(v1, v2): return v1 + v2
result = f(3, 4)
print(result) # before, after, 7
更进一步,装饰器 around
本身也可以携带参数值。为了实现这个目的,下文创建了更深的嵌套。
def around(param):
def deepwarp(ff):
def wrap(*args, **kwargs):
print(param)
print("before")
r = ff(*args, **kwargs)
print("after")
return r
return wrap
return deepwarp
@around(param="decorator param")
def f(v1, v2): return v1 + v2
result = f(3, 4)
print(result) # before, after, 7
我们可以从嵌套层次中总结参数传递的次序:装饰器函数参数 > 目标函数自身 > 目标函数参数。这种嵌套有一个更加专业的术语,即函数柯里化 ( currying )。
作者:花花子
来源:稀土掘金