前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >浅析装饰器的那些事儿

浅析装饰器的那些事儿

作者头像
前端皮皮
发布2021-02-08 09:33:53
2390
发布2021-02-08 09:33:53
举报
文章被收录于专栏:前端进阶学习交流

终是圣明天子事,景阳宫井又何人。

一、装饰器的简单定义

外层函数返回里层函数的引用,里层函数引用外层函数的变量。

二、装饰器的作用

通俗来讲装饰器的作用就是在不改变已有函数代码前提下,为该函数增加新的功能。

代码语言:javascript
复制
def run():
   print('我会跑')
fun()

现在我想在原有函数的基础上新增一个功能:我会唱歌。这个时候利用装饰器则轻松可以帮我们实现这个功能。

三、实例理解

(1)不传参的装饰器

代码语言:javascript
复制
def outer(fun):
   def inner():
      fun()  //fun是外层函数的变量,在inner里面用
   return inner //inner就是里层函数的引用

(2)传递参数的装饰器:

代码语言:javascript
复制
def func(fun):
   def add(*args,**kwarge):
      return fun(*args,**kwargs)
   return add

现在对于装饰器的基本格式有一定的了解,就可以直接写函数了。下面实现文章开头的 我会唱歌 的功能

代码语言:javascript
复制
def outer(fun):
    def inner(*args, **kwarge):
        print("我会唱歌")
        return fun(*args, **kwarge)
    return inner
四、如何使用装饰器
代码语言:javascript
复制
方法一:使用@符号+装饰器的名字   把它放在想要装饰函数的上一行即可
@outer
def run():
   print('我会跑')
   
run()


方法二:
def run():
    print('我会跑')

run=outer(run)   #就等价于@outer
run()

最终打印结果是:
我会唱歌
我会跑

如果我想知道fun 传递的参数是什么,在装饰器内部可以使用如下方式:

代码语言:javascript
复制
def outer(fun):
    a = 1
    def inner(*args, **kwarge): # args是一个数组,kwargs一个字典
        print(fun.__name__) #打印fun接收的函数的名字
        print("我会唱歌")
        return fun(*args, **kwarge)
    return inner

但是如果我们 print(run.__name__,6666666) 输出的结果是inner,并不是我们想要的run,这里的函数被warpTheFunction替代了。它重写了我们函数的名字和注释文档(docstring)。解决方法如下:

代码语言:javascript
复制
from functools import wraps

def outer(fun):
    @wraps(fun)
    def inner(*args, **kwargs):
        print(fun.__name__,11111111111)
        print("我会唱歌")
        return fun(*args, **kwargs)
    return inner

@outer
def run():
   print('我会跑')
   
 print(run.__name__,6666666)  //输出结果为 run 666666
五、自己实现装饰器
代码语言:javascript
复制
def subuser_keymanage(view_func):
    '''功能是实现用户管理权限的判定'''
    def _wrapper_view(request, *args, **kwargs):
        user = request.user #一个Customer对象,包含了用户名/密码等信息
        customer = user.customer.customer_id #用户的id
        select_status = get_curuser_permission(user=user, customer=customer)#调用函数返回的值有两种0和1
        if not select_status:#如果返回0表示没有权限,返回错误码
            return render_response(request, ErrorCode.FAILED)
        return view_func(request, *args, **kwargs)
    return _wrapper_view
代码语言:javascript
复制
@subuser_keymanage 
def generate_subuser_ak_sk(request):
    params = json.loads(request.body) #获取卡前端传递的参数
    user_id_only = params.get("user_id") #获取用户表示id值
    中间代码就忽略了......
    return render_response(request, ErrorCode.FAILED)
六、装饰器小结

通过装饰器很大程度上可以减少代码的复用,在代码规范中这一点是很重要的。

以上就是装饰器的基本知识,即便没有任何基础,按照作者的思路,套用固定的格式,不需要完全理解,只要按照流程一步一步就能写出高端大气上档次的装饰器了,恭喜你!

前方高能请注意:装饰器传参,三层嵌套函数一般用的比较少,其实也不难,一层一层看,跟上文讲的一样,仅作为知识的拓宽。

代码语言:javascript
复制
import logging
def use_logging(level):
    def decorator(func):
        def wrapper(*args, **kwargs):
            if level == "warn":
                logging.warn("%s is running" % func.__name__)
            elif level == "info":
                logging.info("%s is running" % func.__name__)
            return func(*args)
        return wrapper

    return decorator

@use_logging(level="warn")
def foo(name='foo'):
    print("i am %s" % name)

foo()
代码语言:javascript
复制
i am foo
WARNING:root:foo is running

如果在操作过程中有任何问题,记得下面留言,我们看到会第一时间解决问题。

看完本文有收获?请转发分享给更多的人

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2021-02-01,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 IT共享之家 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 一、装饰器的简单定义
    • 二、装饰器的作用
      • 三、实例理解
        • 四、如何使用装饰器
          • 五、自己实现装饰器
            • 六、装饰器小结
            领券
            问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档