笔记-python-装饰器
1. 装饰器
1.1. 开始
在Python中,函数也是一种对象
def foo(x):
print(x)
print(type(foo))
>>><class 'function'>
查看函数拥有的方法:
dir(foo)
>>>
['__call__',
'__class__',
'__closure__',
'__code__',
'__defaults__',
'__delattr__',
……]
因为函数是对象,所以函数可以作为参数传入另一个函数:
def bar(f, x):
x += 1
f(x)
bar(foo, 4)
5
1.2. 返回函数
修饰函数是这样的一种函数,它接受一个函数作为输入,通常输出也是一个函数:
def loud(f):
def new_func(*args, **kw):
print 'calling with', args, kw
rtn = f(*args, **kw)
print 'return value is', rtn
return rtn
return new_func
loudlen = loud(len)
loudlen([10, 20, 30])
>>>
calling with ([10, 20, 30],) {}
return value is 3
>>> loudlen
<function loud.<locals>.new_func at 0x000000894F4A2E18>
>>> len
<built-in function len>
在python中变量其实都是指针,对象、包括函数也是,可以相互赋值,下面也是合法的语句,在这个基础上理解容易得多;
loudlen1 = loudlen
loudlen1([10,20,30])
1.3. 使用 @
@是一个语法糖,与其说是修饰函数倒不如说是引用、调用它修饰的函数。
下面的一段代码,里面两个函数,没有被调用,也会有输出结果:
def test(f):
print "before ..."
f()
print "after ..."
@test
def func():
print "func was called"
直接运行,输出结果:
before ...
func was called
after ...
上面代码可以看出来,只定义了两个函数: test和func。没有地方调用它们。如果没有“@test”,运行应该是没有任何输出的。
但是,Python解释器读到函数修饰符“@”的时候,后面步骤会是这样了:
1. 去调用 test函数,test函数的入口参数就是那个叫“func”的函数;
2. test函数被执行,入口参数的(也就是func函数)会被调用(执行);
换言之,修饰符带的那个函数的入口参数,就是下面的那个整个的函数。
再来看一个例子:
def test(func):
func()
print("call test")
def test1(f):
f()
print( "call test1")
def main():
@test
def fun():
print("call fun")
@test1
def fun1():
print( "call fun1")
main()
输出结果:
call fun
call fun1
call test1
call test
需要注意的:
1. 函数先定义,再修饰它;反之会编译器不认识;
2. 修饰符“@”后面必须是之前定义的某一个函数;
1.4. 带参数的装饰器
上面都是无参数装饰,下面是一个有参数装饰的例子:
def log(text):
def decorator(func):
def wrapper(*args, **kw):
print("%s %s():" %(text, func.__name__))
return func(*args, **kw)
return wrapper
return decorator
@log("execute")
def now():
print("time.ctime()")
now()
输出:
execute now()
time.ctime()
上面的@log(“execute“)等价于
now = log(“execute”)(now)
2. 附录:
面向切面编程AOP (Aspect Oriented Programming):
AOP主要实现的目的是针对业务处理过程中的切面进行提取,它所面对的是处理过程中的某个步骤或阶段,以获得逻辑过程中各部分之间低耦合性的隔离效果。