执行w1函数 ,并将 @w1 下面的函数作为w1函数的参数,即:@w1 等价于 w1(f1) 所以,内部就会去执行:
def inner(): #验证 1 #验证 2 #验证 3 f1() # func是参数,此时 func 等于 f1 return inner# 返回的 inner,inner代表的是函数,非执行函数 ,其实就是将原来的 f1 函数塞进另外一个函数中 w1的返回值将执行完的w1函数返回值 赋值 给@w1下面的函数的函数名f1 即将w1的返回值再重新赋值给 f1,即:
新f1 = def inner(): #验证 1 #验证 2 #验证 3 原来f1() return inner所以,以后业务部门想要执行 f1 函数时,就会执行 新f1 函数,在新f1 函数内部先执行验证,再执行原来的f1函数,然后将原来f1 函数的返回值返回给了业务调用者。
如此一来, 即执行了验证的功能,又执行了原来f1函数的内容,并将原f1函数返回值 返回给业务调用着
Low BBB 你明白了吗?要是没明白的话,我晚上去你家帮你解决吧!!!
3. 手动实现一个简单的装饰器 def set_fun(fun): def call_fun(): print("---这是权限验证---") fun() return call_fun def test(): print("---test---") test = set_fun(test) # 手动调用set_fun函数,此函数返回对原来的test函数进行装饰了的函数引用 test()test函数是待装饰的函数,set_fun函数接收一个函数作为参数,并返回对接受的参数中的函数进行装饰后的函数。执行test = set_fun(test)这句话会将装饰后的函数的引用给到test,最后test引用的是装饰后的函数。
4. 装饰器(decorator)功能引入日志
函数执行时间统计
执行函数前预备处理
执行函数后清理功能
权限校验等场景
缓存
5. 装饰器示例 例1:无参数的函数 import time def timefun(fun): def call_fun(): start = time.time() fun() print("cost %fms" % (time.time() - start)) return call_fun @timefun def foo(): print("foo") foo()上面代码理解装饰器执行行为可理解成
foo = timefun(foo) # foo先作为参数赋值给fun后,foo接收指向timefun返回的call_fun foo() # 调用foo(),即等价调用call_fun() # 内部函数call_fun引用,所以外部函数的fun变量(自由变量)并没有释放 # fun里保存的是原foo函数对象 例2:被装饰的函数有参数 import time def timefun(fun): def call_fun(a, b): start = time.time() fun(a, b) print("cost %fms" % (time.time() - start)) return call_fun @timefun def foo(a, b): print(a + b) foo(1, 2) 例3:被装饰的函数有不定长参数 import time def timefun(fun): def call_fun(*args, **kwargs): start = time.time() fun(*args, **kwargs) print("cost %fms" % (time.time() - start)) return call_fun @timefun def foo(a, b, c,): print(a + b + c) print("name=%s" % name) foo(1, 2, 3) foo(3, 4, 5,) 例4:装饰器中的return import time def timefun(fun): def call_fun(): start = time.time() ret = fun() print("cost %fms" % (time.time() - start)) return ret return call_fun @timefun def foo(): return "6666" ret = foo() print(ret) 例5:多个装饰器对同一个函数进行装饰 import time def timefun(fun): def call_fun(): print("--计算花费的时间--") start = time.time() fun() print("cost %fms" % (time.time() - start)) return call_fun def add_privilege(fun): def call_fun(): print("--进行权限验证--") fun() return call_fun @timefun @add_privilege def foo(): print("foo") foo()运行结果:
--计算花费的时间-- --进行权限验证-- foo cost 0.000032ms 例6:类装饰器装饰器函数其实是这样一个接口约束,它必须接受一个callable对象作为参数,然后返回一个callable对象。在Python中一般callable对象都是函数,但也有例外。只要某个对象重写了 __call__() 方法,那么这个对象就是callable的。
class Test(): def __call__(self): print('call me!') t = Test() t() # call me类装饰器demo
class Test(object): def __init__(self, fun): self.fun = fun def __call__(self): print("--call--") self.fun() @Test def foo(): print("--foo--") foo() 例7:装饰器带参数,在原有装饰器的基础上,设置外部变量 #decorator2.py from time import ctime, sleep def timefun_arg(pre="hello"): def timefun(func): def wrapped_func(): print("%s called at %s %s" % (func.__name__, ctime(), pre)) return func() return wrapped_func return timefun # 下面的装饰过程 # 1. 调用timefun_arg("itcast") # 2. 将步骤1得到的返回值,即time_fun返回, 然后time_fun(foo) # 3. 将time_fun(foo)的结果返回,即wrapped_func # 4. 让foo = wrapped_fun,即foo现在指向wrapped_func @timefun_arg("itcast") def foo(): print("I am foo") @timefun_arg("python") def too(): print("I am too") foo() sleep(2) foo() too() sleep(2) too()可以理解为
foo()==timefun_arg("itcast")(foo)()