向装饰器添加参数的最佳方法是什么?(日志)

[解决方案1]:

简短的回答是否定的,但是你可以修改装饰器函数的代码;例如:

def decorator(func):
    def inner(*args,**kwargs):
        return func(*args,**kwargs)
    return inner

这是一个标准的装饰器函数,我们稍作修改。

你可以这样做:

def decorator(func,defaultdescription,defaultnum):
    def inner(description=defaultdescription,num=defaultnum,*args,**kwargs):
        print("function",func.__code__.co_name,"with description",description,"with number",num)
        return func(*args,**kwargs)
    return inner

所以你可以更改函数的描述

【讨论】:

[解决方案2]:

基本上,装饰器是内部的另一个函数,它在完成时调用您的函数。如果您打算使用自己的装饰器,则必须有一个内部函数来执行所需的任务并调用使用装饰器函数的函数。你可以使用 *args 和 **kwargs

以下代码是python装饰器的基本实现

# Python code to illustrate
# Decorators basic in Python
def decorator_fun(func):

图片[1]-向装饰器添加参数的最佳方法是什么?(日志)-唐朝资源网

def inner(*args, **kwargs): """ do your actual task here """ for argv in args: print(argv) for key in kwargs: print(key) #returning to function which used the decorator at last func() return inner @decorator_fun def func_to(): print("Inside actual function") func_to("hello",{"test": "value 1"})

【讨论】:

[解决方案3]:

正如其他人在这里所写,装饰器是函数的语法糖(即,使程序更易于阅读、编写或理解),它将另一个函数作为参数并从内部激活它。

图片[2]-向装饰器添加参数的最佳方法是什么?(日志)-唐朝资源网

所以,用装饰器调用这个“Add()”函数,如下所示:

@wrapper()
def Add(x: int, y: int):
    return x + y

这就像使用“Add”函数作为变量调用“wrapper”函数一样。像这样:

wrapper(Add)(x,y) # pass x,y to wrapper that pass it to Add function.

因此(我发现)向装饰器添加参数的最佳方法是将其全部嵌套在另一个包含子装饰器的函数下。例如:

@deco_maker(msg: str)
def Add(x: int, y: int):
    return x + y

看起来像这样:

deco_maker(msg)(wrapper(Add))(x,y)

所以,这是一个简单的包装装饰器,它记录一个没有参数的函数调用,如下所示:

def wrapper(func: Callable):
    def wrapper_func(*args, **kwargs):
        logging.DEBUG f"Function '{func.__name__}' called with args: {[str(arg) for arg in args]}."
        value = func(*args, **kwargs)
        return value
    return wrapper_func

这里是带有相关日志记录参数的扩展装饰器(日志名称和级别以获得更大的灵活性):

图片[3]-向装饰器添加参数的最佳方法是什么?(日志)-唐朝资源网

def log_func_calls(logger_name: str, log_level: int):
    def wrapper(func: Callable):
        def wrapper_func(*args, **kwargs):
            logger = logging.getLogger(logger_name)
            logger.log(
                    level=log_level,
                    msg=f"Function '{func.__name__}' called with args: {[str(arg) for arg in args]}."
                    )
            value = func(*args, **kwargs)
            return value
        return wrapper_func
    return wrapper

这是一个参数化装饰器的完整代码示例,它记录一个函数调用并在它之后打印日志文件输出。

例子:

import logging
from typing import Callable
# define app logger with file and console handlers
def setup_logging():
    logger = logging.getLogger('test_app')
    logger.setLevel(logging.DEBUG)
    # create file handler which logs even debug messages
    fh = logging.FileHandler('test.log')
    fh.setLevel(logging.DEBUG)

图片[4]-向装饰器添加参数的最佳方法是什么?(日志)-唐朝资源网

# create formatter and add it to the file handler formatter = logging.Formatter('{asctime} | {name} | {levelname:^8s} | {message}', style='{') fh.setFormatter(formatter) # add the handler to the logger logger.addHandler(fh) return logger # define a log decorator to trace function calls def log_func_calls(logger_name: str, log_level: int): def wrapper(func: Callable): def wrapper_func(*args, **kwargs): logger = logging.getLogger(logger_name) logger.log( level=log_level, msg=f"Function '{func.__name__}' called with args: {[str(arg) for arg in args]}." ) value = func(*args, **kwargs) return value return wrapper_func return wrapper # sample usage 1 @log_func_calls(logger_name='test_app', log_level=logging.DEBUG) def Add(x: int, y: int): return x + y # sample usage 2 @log_func_calls(logger_name='test_app', log_level=logging.DEBUG) def Sub(x: int, y: int): return x - y # a test run def main(): logger = setup_logging() logger.info("<<>>") print(Add(50,7)) print(Sub(10,7)) print(Add(50,70)) logger.info("<<>>") if __name__ == "__main__": main()

还有日志输出:

...
2022-06-19 23:34:52,656 | test_app |  DEBUG   | Function 'Add' called with args: ['50', '7'].
2022-06-19 23:34:52,656 | test_app |  DEBUG   | Function 'Sub' called with args: ['10', '7'].
2022-06-19 23:34:52,657 | test_app |  DEBUG   | Function 'Add' called with args: ['50', '70'].
...

【讨论】:

© 版权声明
THE END
喜欢就支持一下吧
点赞97 分享
评论 抢沙发
头像
欢迎您留下宝贵的见解!
提交
头像

昵称

取消
昵称表情代码图片