详解Python实现同时支持带调用和不调用带装饰器

 更新时间:2023年06月13日 11:28:13   作者:临渊  
一般来说,不带参数装饰器,再使用时不加括号,带参数的装饰器使用时必须加括号,这篇文章主要介绍了Python实现同时支持带调用和不调用带装饰器的相关知识,需要的朋友可以参考下

一般来说,不带参数装饰器,再使用时不加括号,带参数的装饰器使用时必须加括号。例如

  • 不带参装饰器
def info(func):  # 装饰器,参数接收一个函数,返回一个函数
    @functools.wraps(func)
    def wrapper(*args, **kwargs):   # 与原函数功能一致,支持任意参数
        print(f'调用函数: {func.__name__} 参数:{args} {kwargs}')
        return func(*args, **kwargs)   # 内部包裹调用原函数
    return wrapper  # 返回和原函数功能一致的函数
@info   # 使用时不加括号
def add(a, b):
    return a + b
  • 带参数的装饰器(返回装饰器的函数)
def info(show_result=True):
    def _info(func):  # 装饰器,参数接收一个函数,返回一个函数
        @functools.wraps(func)
        def wrapper(*args, **kwargs):  # 与原函数功能一致,支持任意参数
            print(f'调用函数: {func.__name__} 参数:{args} {kwargs}')
            start_time = time.time()
            result = func(*args, **kwargs)  # 内部包裹调用原函数
            if show_result is True:
                print(f'调用结果: {result} 耗时: {time.time()-start_time}')
            return result
        return wrapper  # 返回替换后的新函数
    return _info
@info()  # 即使使用默认参数也必须加括号调用(因为调用后才能得到装饰器)
def add(a, b):
    return a + b

注意: 带参数装饰器虽然通过参数支持定制,但是使用时必须加括号,用户很容易遗漏或分不清是否需要加括号

能不能像@pytest.fixture那样,既可以不带参数,也可以带参数使用呢,例如:

import pytest
@pytest.fixture
def a(): ...
@pytest.fixture()
def b(): ...
@pytest.fixture(scope='module')
def c(): ...

这就要求,我们装饰器外部函数,即可以本身作为一个装饰器(接收一个原函数,返回一个同功能函数),也可以根据参数调用后返回一个装饰器,实现如下:

def info(func=None, show_result=False):  # 第一个参数为函数
    def _info(func):  # 装饰器,参数接收一个函数,返回一个函数
        @functools.wraps(func)
        def wrapper(*args, **kwargs):  # 与原函数功能一致,支持任意参数
            print(f'调用函数: {func.__name__} 参数:{args} {kwargs}')
            start_time = time.time()
            result = func(*args, **kwargs)  # 内部包裹调用原函数
            if show_result is True:
                print(f'调用结果: {result} 耗时: {time.time()-start_time}')
            return result
        return wrapper  # 返回替换后的新函数
    if func is not None:  # 不带括号(作为装饰器)使用时
        return _info(func)  # 返回 同功能函数wrapper(即_info的调用结果)
    return _info  # 否则,带括号调用(作为返回装饰器的函数)使用时,返回装饰器 _info
@info  # 即使使用默认参数也必须加括号调用(因为调用后才能得到装饰器)
def add(a, b):
    return a + b
@info()
def sub(a, b):
    return a - b
@info(show_result=True)
def mul(a, b):
    return a * b

注意:1. 在使用装饰器info()不能手动指定第一个参数func=...
2. 在指定参数时,只能按key=value形式给出

到此这篇关于Python实现同时支持带调用和不调用带装饰器的文章就介绍到这了,更多相关python带调用和不调用带装饰器内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • Python的Lambda函数用法详解

    Python的Lambda函数用法详解

    在Python中有两种函数,一种是def定义的函数,另一种是lambda函数,也就是大家常说的匿名函数。这篇文章主要介绍了Python的Lambda函数用法,需要的朋友可以参考下
    2019-09-09
  • Python 实现二叉查找树的示例代码

    Python 实现二叉查找树的示例代码

    这篇文章主要介绍了Python 实现二叉查找树的示例代码,帮助大家更好的理解和使用python,感兴趣的朋友可以了解下
    2020-12-12
  • Python实现简单购物车小程序

    Python实现简单购物车小程序

    这篇文章主要为大家详细介绍了Python实现简单购物车小程序,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2022-02-02
  • 详解Python中4种超参自动优化算法的实现

    详解Python中4种超参自动优化算法的实现

    要想模型效果好,每个算法工程师都应该了解的流行超参数调优技术。今天给大家总结超参自动优化方法:网格搜索、随机搜索、贝叶斯优化 和 Hyperband,感兴趣的可以了解一下
    2022-05-05
  • 查看python安装路径及pip安装的包列表及路径

    查看python安装路径及pip安装的包列表及路径

    这篇文章主要介绍了查看python安装路径及pip安装的包列表及路径,本文给大家介绍的非常详细,具有一定的参考借鉴价值,需要的朋友可以参考下
    2019-04-04
  • python对输出的奇数偶数排序实例代码

    python对输出的奇数偶数排序实例代码

    在本篇内容里小编给大家整理的是一篇关于python对输出的奇数偶数排序实例代码内容,有兴趣的朋友们可以参考下。
    2020-12-12
  • Python的Asyncore异步Socket模块及实现端口转发的例子

    Python的Asyncore异步Socket模块及实现端口转发的例子

    asyncore模块是封装过的处理socket事件的模块,采用异步的处理方式,这里我们讲来讲解Python的Asyncore异步Socket模块及实现端口转发的例子,需要的朋友可以参考下
    2016-06-06
  • django连接mysql配置方法总结(推荐)

    django连接mysql配置方法总结(推荐)

    这篇文章主要介绍了django连接mysql配置方法总结(推荐),小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2018-08-08
  • Python数据可视化探索实例分享

    Python数据可视化探索实例分享

    这篇文章主要介绍了Python数据可视化探索实例分享,数据可视化是指用图形或表格的方式来呈现数据,关于更多相关介绍需要的小伙伴可以参考下面文章的具体内容
    2022-05-05
  • Python下opencv使用hough变换检测直线与圆

    Python下opencv使用hough变换检测直线与圆

    在数字图像中,往往存在着一些特殊形状的几何图形,像检测马路边一条直线,检测人眼的圆形等等,有时我们需要把这些特定图形检测出来,本文就详细的介绍了一下方法
    2021-06-06

最新评论