简体   繁体   中英

How to use class attributes in method decorators in Python?

I have a decorator responsible for logging. Eg something like this:

import logging
import functools
from typing import Callable


def log_container(func: Callable, logger=None):
    if logger is None:
        logger = logging.getLogger("default")
    @functools.wraps(func)
    def wrapper(*args, **kwargs):
        logger.info(f"{func.__qualname__} started.")
        result = func(*args, **kwargs)
        logger.info(f"{func.__qualname__} ended.")
        return result

    return wrapper

I have a class that has a distinct logger as an attribute, and I want to give that logger as a decorator argument. Is this possible? and if so, how?

class Dummy:
    logger = logging.getLogger("Dummy")
    
    @log_container(logger=Dummy.logger)
    def do_something(self):
        pass

Your decorator, as its currently defined, wouldn't work. You can't pass in the decorated function together with an argument since the decorator itself only accepts one argument: the func itself. If you want your decorator to accept an argument, you'll need to nest the decorator one level deeper. Which now becomes a function that returns a decorator:

def log_container(logger=None):
    if logger is None:
        logger = logging.getLogger("default")

    def inner(func: Callable):
        @functools.wraps(func)
        def wrapper(*args, **kwargs):
            logger.info(f"{func.__qualname__} started.")
            result = func(*args, **kwargs)
            logger.info(f"{func.__qualname__} ended.")
            return result

        return wrapper
    return inner

Then when decorating the method for the Dummy class, don't use Dummy.logger since Dummy won't be defined until the end of the class definition, instead, you can access the class attribute logger directly.

class Dummy:
    logger = logging.getLogger("Dummy")
    
    @log_container(logger=logger)
    def do_something(self):
        pass

    # Use default logger
    @log_container()
    def do_something_else(self):
        pass

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM