简体   繁体   English

使用装饰器将参数添加到装饰函数

[英]Use decorator to add an argument to the decorated function

Let's say I have a function foo that logs some info during execution:假设我有一个函数foo在执行期间记录一些信息:

import logging

logging.basicConfig()

def foo(x):
    for i in range(10):
        logging.info(f"This is iteration number {i}.")
        x += i
    return x

Is it possible to create a decorator log_or_not so that I can call my decorated function foo with an added argument like this:是否可以创建一个装饰器log_or_not以便我可以调用我的装饰函数foo并添加如下参数:

foo(level=logging.INFO)

For now all I have is this, a decorator that sets the logging level to INFO, executes the function then returns the logging level to the original level:现在我只有这个,一个将日志记录级别设置为 INFO 的装饰器,执行该函数然后将日志记录级别返回到原始级别:

def log_or_not(func):
    def wrap_function(*args, **kwargs):
        original_level = logging.root.level
        print(original_level)
        logging.getLogger().setLevel(logging.INFO)
        y = func(*args, **kwargs)
        logging.getLogger().setLevel(original_level)
        return y
    return wrap_function

@log_or_not
def foo(x):
    for i in range(10):
        logging.info(f"This is iteration number {i}.")
        x += i
    return x

Add the extra parameter to your wrap_function :将额外参数添加到您的wrap_function

import logging

def log_or_not(func):
    def wrap_function(*args, level=logging.INFO, **kwargs):
        original_level = logging.root.level
        print(original_level)
        logging.getLogger().setLevel(level)
        try:
            return func(*args, **kwargs)
        finally:
            logging.getLogger().setLevel(original_level)
    return wrap_function

Using try/finally guarantees that you'll reset the original logging level after calling func even if it raises an exception.使用try/finally可以保证您在调用func后重置原始日志记录级别,即使它引发了异常。

Since wrap_function takes the place of the decorated function, you can now do:由于wrap_function取代了装饰函数,您现在可以执行以下操作:

@log_or_not
def foo(x):
    for i in range(10):
        logging.info(f"This is iteration number {i}.")
        x += i
    return x

foo(0, level=logging.ERROR)  # logs with level ERROR
foo(0)                       # logs with level INFO (default)

I would use a context manager to modify logging levels on the fly, and leave the function itself alone.我会使用上下文管理器来动态修改日志记录级别,而让函数本身保持独立。

import contextlib

# No try needed; the context manager decorator already 
# ensures that the post-yield code is executed before  
# propagating any exceptions.
@contextlib.contextmanager
def change_level(lvl):
    original = logging.root.level
    logging.getLogger().setLevel(lvl)
    yield
    logging.getLogger().setLevel(original)


# instead of foo(0, level=logging.ERROR)
with change_level(logging.INFO):
    foo(0)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 使用装饰器更改已装饰 function 的参数 - Use decorator to change argument of a decorated function 如何在装饰器中使用 pytest 固定装置而不将其作为装饰 function 的参数 - How to use pytest fixtures in a decorator without having it as argument on the decorated function 在Python装饰器中创建参数以供装饰函数使用 - Creating parameters in a Python decorator for use by the decorated function 在Python 3中访问装饰器内部装饰函数的关键字参数失败 - Accessing keyword argument of decorated function inside the decorator fails in Python 3 类中的装饰器:无法在装饰函数内部使用self - Decorator in class: cannot use self inside the decorated function 带装饰函数参数的python decorator - python decorator with arguments of decorated function 如何在装饰器中使用上下文管理器以及如何将在decorator中创建的对象传递给装饰函数 - How to use a context manager inside a decorator and how to pass an object created in decorator to decorated function 传入装饰的参数 function - Argument passing in decorated function 当我调用内部/装饰函数时,我可以将参数传递给我的装饰器函数吗? - Can I pass an argument into my decorator function when I call the inner/decorated function? 如何将装饰器中的变量传递给装饰函数中的函数参数? - How can I pass a variable in a decorator to function's argument in a decorated function?
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM