python三大器之装饰器详解

这篇文章主要介绍了Python中的装饰器,涉及到Python中很多重要的特性,小编觉得这篇文章写的还不错,需要的朋友可以参考下

装饰器

讲装饰器之前要先了解两个概念:

  • 对象引用 :对象名仅仅只是个绑定内存地址的变量
 def func():   # 函数名仅仅只是个绑定内存地址的变量 print("i`m running") # 这是调用 func()  # i`m running # 这是对象引用,引用的是内存地址 func2 = func print(func2 is func)  # True # 通过引用进行调用 func2()  # i`m running 
  • 闭包:定义一个函数A,然后在该函数内部再定义一个函数B,并且B函数用到了外边A函数的变量
     def out_func(): out_a = 10 def inner_func(inner_x): return out_a + inner_x return inner_func out = out_func() print(out)  # .inner_func at 0x7ff378af5c10> out_func返回的是inner_func的内存地址 print(out(inner_x=2))  # 12 

装饰器和闭包不同点在于:装饰器的入参是函数对象,闭包入参是普通数据对象

 def decorator_get_function_name(func): """ 获取正在运行函数名 :return: """ def wrapper(*arg): """ wrapper :param arg: :return: """ print(f"当前运行方法名:{func.__name__}  with  params: {arg}") return func(*arg) return wrapper @decorator_get_function_name def test_func_add(x, y): print(x + y) @decorator_get_function_name def test_func_sub(x, y): print(x - y) test_func_add(1, 2) # 当前运行方法名:test_func_add  with  params: (1, 2) # 3 test_func_sub(3, 5) # 当前运行方法名:test_func_sub  with  params: (3, 5) # -2 

常用于如鉴权校验,例如笔者会用于登陆校验:

 def login_check(func): def wrapper(request, *args, **kwargs): if not request.session.get('login_status'): return HttpResponseRedirect('/api/login/') return func(request, *args, **kwargs) return wrapper @login_check def edit_config(): pass 

装饰器内部的执行逻辑:

 """ >  1. def login_check(func):  ==>将login_check函数加载到内存 >  .... >  @login_check  ==>此处已经在内存中将login_check这个函数执行了!;并不需要等edit_config()实例化调用 >  2. 上例@login_check内部会执行以下操作: >	  2.1 执行login_check函数,并将 @login_check 下面的 函数(edit_config) 作为login_check函数的参数,即:@login_check 等价于 login_check(edit_config) >     2.2 内部就会去执行: def wrapper(*args): # 校验session... return func(request, *args, **kwargs)   # func是参数,此时 func 等于 edit_config,此处相当于edit_config(request, *args, **kwargs) return wrapper     # 返回的 wrapper,wrapper代表的是函数对象,非函数实例化对象 2.3 其实就是将原来的 edit_config 函数塞进另外一个函数中,另一个函数当中可以做一些操作;再执行edit_config 2.4 将执行完的 login_check 函数返回值(也就是 wrapper对象)将此返回值再重新赋值给新 edit_config,即: 2.5 新edit_config = def wrapper: # 校验session... return 原来edit_config(request, *args, **kwargs) >  3. 也就是新edit_config()=login_check(edit_config):wrapper(request, *args, **kwargs):return edit_config(request, *args, **kwargs) 有点绕,大家看步骤细细理解。 """ 

同样一个函数也可以使用多个装饰器进行装饰,执行顺序从上到下

 from functools import wraps def w1(func): @wraps(func) def wrapper(*args, **kwargs): print("这里是第一个校验") return func(*args, **kwargs) return wrapper def w2(func): @wraps(func) def wrapper(*args, **kwargs): print("这里是第二个校验") return func(*args, **kwargs) return wrapper def w3(func): def wrapper(*args, **kwargs): print("这里是第三个校验") return func(*args, **kwargs) return wrapper @w2  # 这里其实是w2(w1(f1)) @w1  # 这里是w1(f1) def f1(): print(f"i`m f1, at {f1}") @w3 def f2(): print(f"i`m f2, at {f2}") # ====================== 实例化阶段 ===================== f1() # 这里是第二个校验 # 这里是第一个校验 # i`m f1, at  f2() # 这里是第三个校验 # i`m f2, at 

有同学可能要好奇 为什么f1对象打印的是“”,f2对象打印的是“”(也就是步骤2.5造成的,赋的值是wrapper对象),这就跟w1和w2 内部wrapper使用的wraps装饰器有关系了。

wraps的作用是:被修饰的函数(也就是里面的func)的一些属性值赋值给修饰器函数(wrapper)包括元信息和“函数对象”等。

同时装饰器也可以接受参数:

 def decorator_get_function_duration(enable): """ :param enable:  是否需要统计函数执行耗时 :return: """ print("this is decorator_get_function_duration") def inner(func): print('this is inner in decorator_get_function_duration') @wraps(func) def wrapper(*args, **kwargs): print('this is a wrapper in decorator_get_function_duration.inner') if enable: start = time.time() print(f"函数执行前:{start}") result = func(*args, **kwargs) print('[%s]`s enable was %s it`s duration : %.3f s ' % (func.__name__, enable, time.time() - start)) else: result = func(*args, **kwargs) return result return wrapper return inner def decorator_1(func): print('this is decorator_1') @wraps(func) def wrapper(*args, **kwargs): print('this is a wrapper in decorator_1') return func(*args, **kwargs) return wrapper def decorator_2(func): print('this is decorator_2') @wraps(func) def wrapper(*args, **kwargs): print('this is a wrapper in decorator_2') return func(*args, **kwargs) return wrapper @decorator_1 # 此处相当:decorator_1(decorator_2(decorator_get_function_duration(enable=True)(fun))) @decorator_2 # = decorator_2(decorator_get_function_duration(enable=True)(fun)) @decorator_get_function_duration(enable=True)  # = decorator_get_function_duration(enable=True)(fun) def fun(): time.sleep(2) print("fun 执行完了~") fun() # ======== enable=False ============ """ this is decorator_get_function_duration this is inner in decorator_get_function_duration this is decorator_2 this is decorator_1 this is a wrapper in decorator_1 this is a wrapper in decorator_2 this is a wrapper in decorator_get_function_duration.inner fun 执行完了~ """ # ======== enable=True ============ """ this is decorator_get_function_duration this is inner in decorator_get_function_duration this is decorator_2 this is decorator_1 this is a wrapper in decorator_1 this is a wrapper in decorator_2 this is a wrapper in decorator_get_function_duration.inner 函数执行前:1634635708.648994 fun 执行完了~ [fun]`s enable was True it`s duration : 2.002 s """ 

总结

本篇文章就到这里了,希望能够给你带来帮助,也希望您能够多多关注0133技术站的更多内容!

以上就是python三大器之装饰器详解的详细内容,更多请关注0133技术站其它相关文章!

赞(0) 打赏
未经允许不得转载:0133技术站首页 » python