前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Python3 装饰器理解

Python3 装饰器理解

作者头像
嵌入式视觉
发布2022-09-05 13:57:30
2020
发布2022-09-05 13:57:30
举报
文章被收录于专栏:嵌入式视觉

Contents

在代码运行期间给函数动态增加功能的方式,称之为“装饰器”( Decorator),装饰器的本质是一个返回函数的高阶函数。

装饰器介绍

谈装饰器之前,需明白一件事,Python 中的函数和 Java、C++ 不一样,Python 中的函数可以像普通变量一样当做参数传递给另外一个函数,代码示例如下:

代码语言:javascript
复制
def foo():
    print('hello world')
def decorator(function):
    function()
decorator(foo)

装饰器本质上是一个能返回函数的高阶函数它可以让其他函数或类在不需要做任何代码修改的前提下增加额外功能,装饰器的返回值也是一个函数/类对象。它经常用于有切面需求的场景,比如:插入日志、性能测试、事务处理、缓存、权限校验等场景,装饰器是解决这类问题的绝佳设计。有了装饰器,我们就可以抽离出大量与函数功能本身无关的雷同代码到装饰器中并继续重用。概括的讲,装饰器的作用就是为已经存在的对象添加额外的功能。 简单装饰器示例代码如下:

代码语言:javascript
复制
import logging
def use_logging(func):
    def wrapper():
        logging.warn("%s is running" % func.__name__)
        return func()
    return wrapper
def foo():
    print('I am foo')
foo = use_logging(foo) # 因为装饰器 use_logging(foo) 返回的是函数对象 wrapper,这条语句相当于 foo = wrapper
foo()

程序输出如下:

WARNING:root:foo is running  I am foo

@语法糖

Python 内置的 @property 装饰器是负责把一个方法变成属性调用的,有了 @,就可以省去foo = use_logging(foo)这一句,直接调用 foo() 即可实现相同的功能。

代码语言:javascript
复制
def use_logging(func):
    def wrapper():
        logging.warn("%s is running" % func.__name__)
        return func()
    return wrapper
@use_logging
def foo():
    print("i am foo")
foo()

有了 Python 的 @ 语法,把 decorator 置于函数 foo 定义处,调用 foo 函数,相当于执行语句 foo = use_logging(foo)

args、*kwargs,可变参数与关键字参数

可以在定义 wrapper 函数的时候指定参数,参数可以是可变参数 *args、关键字参数**kwargs。

可变参数允许你传入 0 个或任意个参数,这些可变参数在函数调用时自动组装为一个 tuple。而关键字参数允许你传入 0 个或任意个含参数名的参数,这些关键字参数在函数内部自动组装为一个 dict

给 wrapper 函数添加参数的示例代码如下:

代码语言:javascript
复制
def wrapper(*args, **kwargs):
        # args是一个数组,kwargs一个字典
        logging.warn("%s is running" % func.__name__)
        return func(*args, **kwargs)
    return wrapper

带参数的装饰器

装饰器还有更大的灵活性,例如带参数的装饰器,在上面的装饰器调用中,该装饰器接收唯一的参数就是执行业务的函数 foo 。装饰器的语法允许我们在调用时,提供其它参数,比如 @decorator(a)。示例代码如下:

代码语言:javascript
复制
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="info")
def foo(name='foo'):
    print("i am %s" % name)
foo()

程序输出如下:

i am foo

装饰器示例

可打印函数运行时间的装饰器,代码如下:

代码语言:javascript
复制
# decorator: print the cost time of run function
def runTime(func):
   def wapper(arg, *args, **kwargs):
      print("function name: %s" %func.__name__)
      start = time.time()
      res = func(arg, *args, **kwargs)
      end = time.time()
      print("run time: %.2fs" %(end - start))
      print("="*30)
      return res
   return wapper

总结

实现装饰器知识储备:  a、函数即“变量”  b、高阶函数  c、函数嵌套  d、高阶函数+嵌套函数==》装饰器  在面向对象( OOP)的设计模式中, decorator 被称为装饰模式。 OOP 的装饰模式需要通过继承和组合来实现,而 Python 除了能支持 OOP 的decorator外,直接从语法层次支持 decorator。Python 的 decorator 可以用函数实现,也可以用类实现。

参考资料

理解Python装饰器看这一篇就够了

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2020-11-13,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

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

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

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 装饰器介绍
    • @语法糖
      • args、*kwargs,可变参数与关键字参数
        • 带参数的装饰器
        • 装饰器示例
        • 总结
        • 参考资料
        相关产品与服务
        日志服务
        日志服务(Cloud Log Service,CLS)是腾讯云提供的一站式日志服务平台,提供了从日志采集、日志存储到日志检索,图表分析、监控告警、日志投递等多项服务,协助用户通过日志来解决业务运维、服务监控、日志审计等场景问题。
        领券
        问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档