1 >>> def deco(func):
2 ... print "In deco"
3 ... return func
4 ...
5 >>> @deco
6 ... def foo():
7 ... print "In foo"
8 ...
9 In deco
10 >>>
等等,代码里面还没有调用 foo(),怎么就print “In deco” 了?
这里编写的装饰器根本就没有达到我们要求的功能,因为它返回的还是 func 本身,print “In deco” 也只会在初始化的时候运行一次,仅仅一次。
让我们回到刚开始的例子,在 deco 里面返回了一个 wrapper 函数对象。可以试着这么理解, deco的作用是给 func 进行装饰, wrapper 就是被装饰过的func。
然后我们就可以重复调用这个被装饰过的函数。
四、怎么装饰一个 需要传参数 的函数?
现在另一个问题又来了,前面被装饰的函数都是不带参数的,那带参数的函数要怎么装饰呢?
让我们先尝试下前面的办法:
1 >>> def deco(func):
2 ... def wrapper():
3 ... print "Wrap start"
4 ... func()
5 ... print "Wrap end\n"
6 ... return wrapper
7 ...
8 >>> @deco
9 ... def foo(x):
10 ... print "In foo():"
11 ... print "I have a para: %s" % x
12 ...
13 >>> foo(‘x‘)
14 Traceback (most recent call last):
15 File "<stdin>", line 1, in <module>
16 TypeError: wrapper() takes no arguments (1 given)
报了个缺少参数的错误,那把这个参数带上:
1 >>> def deco(func):
2 ... def wrapper(x):
3 ... print "Wrap start"
4 ... func(x)
5 ... print "Wrap end\n"
6 ... return wrapper
7 ...
8 >>> @deco
9 ... def foo(x):
10 ... print "In foo():"
11 ... print "I have a para: %s" % x
12 ...
13 >>> foo(‘x‘)
14 Wrap start
15 In foo():
16 I have a para: x
17 Wrap end
现在可以正常传递参数了。
五、怎么装饰 参数列表不一样 的多个函数?
继续发散一下,要是想装饰多个函数,但是这些函数的参数列表变化很大的呢?
这个时候,就到了使用Python参数魔法的时候了。
定义函数时:*params:收集其余的位置参数,返回元组。 **params:收集其余的关键字参数,返回字典。
调用函数时:*params:将元组拆分为位置参数传入。 **params:将字典拆分为关键字参数传入。
利用上面的参数魔法后,代码看起来会是这样的:
1 #!/usr/bin/env python
2
3 def deco(func):
4 def wrapper(*args, ** kwargs):
5 print "Wrap start"
6 func(*args, ** kwargs)
7 print "Wrap end\n"
8 return wrapper
9
10 @deco
11 def foo(x):
12 print "In foo():"
13 print "I have a para: %s" % x
14
15 @deco
16 def bar(x,y):
17 print "In bar():"
18 print "I have two para: %s and %s" % (x, y)
19
20 @deco
21 def foo_dict(x,z= ‘dict_para‘):
22 print "In foo_dict:"
23 print "I have two para, %s and %s" % (x, z)
24
25 if __name__ == "__main__" :
26 foo(‘x‘)
27 bar(‘x‘, ‘y‘)
28 foo_dict(‘x‘, z= ‘dict_para‘)
运行一下看看效果:
1 $ python decorate.py
2 Wrap start
3 In foo():
4 I have a para: x
5 Wrap end
6
7 Wrap start
8 In bar():
9 I have two para: x and y
10 Wrap end
11
12 Wrap start
13 In foo_dict:
14 I have two para, x and dict_para
15 Wrap end
本人水平有限,以上如有错误,欢迎指正,谢谢大家 ^_^。