首页 > 编程语言 >Python实现同时支持带调用和不调用带装饰器

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

时间:2023-06-13 11:24:03浏览次数:35  
标签:info 调用 return Python 参数 func time 装饰 def

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

  • 不带参装饰器

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形式给出

标签:info,调用,return,Python,参数,func,time,装饰,def
From: https://www.cnblogs.com/superhin/p/17477020.html

相关文章

  • appium2+Python3+红米手机k40 无法启动APP
    在网上一直找不到解决的方法,困扰了很久。OEM解锁权限和USB调试安全设置也打开试过了,还是不行。有懂的大佬吗!Python报错提示:Message:Anunknownserver-sideerroroccurredwhileprocessingthecommand.Originalerror:ErrorexecutingadbExec.Originalerror:'Command......
  • golang 闭包,装饰器
    packagemainimport( "fmt" "strings")funcmakeSuffixFunc(suffixstring)func(string)string{ returnfunc(namestring)string{ if!strings.HasSuffix(name,suffix){ returnname+suffix } returnname }}funcmain()......
  • pip安装python包
    1.国内源:1)http://mirrors.aliyun.com/pypi/simple/阿里云2)https://pypi.mirrors.ustc.edu.cn/simple/中国科技大学 3)https://pypi.tuna.tsinghua.edu.cn/simple 清华大学2.指定源pip3install-ihttp://mirrors.aliyun.com/pypi/simple/--trusted-hostmirrors.aliyun......
  • vue调用百度api时,跨域问题解决方案
    最近在调用百度地图,文字转语音接口的时候,用vue,js来前端实现转换,及时语音播报,遇到点问题;1.之前直接不用accessToken,一个连接拼接抓取的,已经失效了。2.查看百度文档,更新后的接口,按照文档nodejs格式,一直都是报跨域问题,单独在headers中加'Access-Control-Allow-Origin':'*'无效。......
  • 如何安装安装Python解释器
    安装Python解释器的步骤如下:打开Python官网:https://www.python.org/downloads/,下载最新的Python版本(例如Python3.11.4)。双击下载的安装程序,按照提示一步步进行安装;在安装过程中,要注意勾选“AddPython3.xtoPATH”选项,这样就可以在命令行中直接使用Python命令了。Win+......
  • python 中格式化字符串
     001、format>>>"{0}love{1}.{2}".format("I","FishC","com")##位置参数'IloveFishC.com'>>>"{a}love{b}.{c}".format(a="I",b="FishC"......
  • Python 面向对象之类和对象
    什么叫做面向对象:就是把编程当作一个事物,直接去用,不考虑中间的过程,可与面向过程做比较理解;打个比方:例如:肚子饿了,想吃饭面向过程:去超市---买菜---卖肉---买米---回家---洗菜---切肉---炒菜---煮米饭---盛饭---开吃面向对象:点外卖类和对象:类是抽象的,对象是真实存在的类与对......
  • python 中使用zip实现矩阵转置
     001、[root@PC1test04]#lsa.txttest.py[root@PC1test04]#cata.txt##测试数据010203040506070809101112131415161718192021222324252627282930[root@PC1test04]#cattest.py##测试程序#!/usr/bin/envpython#-*......
  • python: read excel
    pipinstallxlrdpipinstallxlwtpipinstallxlutilspipinstallxlwingspipinstallXlsxWriterpipinstallopenpyxlpipinstallpandaspipinstallpandasql importDrawSquareimportDecoratorsimportxlrdimportxlwtimportxlwingsasxwimportxlsxwriterim......
  • java实现一个接口多个实现类,并且依次调用指定方法
    接口packagecn.daenx.yhchatsdk.mytest;publicinterfaceMyInterface{/***返回-1,后面的实现类将不再执行*返回0,后面的实现类继续执行**@return*/IntegerdoSomething();}实现类实现类1packagecn.daenx.yhchatsdk.mytest;......