了解了@print_a是怎么工作的。现在看一个简单的装饰器。
def print_world(func):
print("world is %s" %func);
def print_hello(func):
print(func);
return print_world;
@print_hello
def print_string(str):
print("传入的参数是:%s" %str);
print_string('123');
分析:
这里的@print_hello,print_hello函数会返回一个print_world 的函数对象,然后替换掉print_string,所以,当你调用print_string的时候,其实执行的是print_world.
所以print_string函数被装饰成了print_world。
运行结果:
可以看到,虽然我调用的是print_string(‘123’);单其实调用的是print_world。
上面的写法是不好的,因为print_world完全和print_string没有关系。已经是换人了,不是化妆了。
所以换一个写法:
def print_hello(func):
def wrapper(*args, **kwargs):
print('Hello');
return func(*args, **kwargs);
return wrapper;
@print_hello
def print_string(str):
print("传入的参数是:%s" %str);
print_string('123');
使用这种写法,就是把print_string函数换成wrapper函数了。wrapper函数先执行了一个print(‘hello’),然后执行func.也就是print_string本来的功能。
这就仿佛是在print_string 函数 每次执行之前,先执行一下其它的东西,也就是print_string被装饰了。
运行结果如下:
你去打印一下print_string的名字,发现它的名字都叫wrapper了,也就是现在print_string已经不是它自己了。
如果要保留print_string自己的名字信息,怎么做呢?
这样写:
from functools import wraps
def print_world(func):
print("world is %s" %func);
def print_hello(func):
@wraps(func)
def wrapper(*args, **kwargs):
print('Hello');
return func(*args, **kwargs);
return wrapper;
@print_hello
def print_string(str):
print("传入的参数是:%s" %str);
print(print_string.__name__);
运行结果:
使用这个wraps工具,在print_hello替换函数之前用@wraps(func)再装饰一下,动动脚指头想想,都知道这个是改函数信息的。