Python中如何将类属性作为参数传递给类方法的装饰器?
问题解答
你的需求完全可以实现,你当前的写法存在两个问题:
- 你写的
log_container装饰器本身不支持带参数调用,直接写@log_container(logger=xxx)会触发参数缺失错误 - 装饰器在类定义阶段就会执行,此时
Dummy类还未完成定义,直接引用Dummy.logger会触发NameError
你可以根据自己的使用场景选择以下两种实现方案:
方案1:最小改动适配(无需修改原有装饰器逻辑)
如果不想调整已经写好的log_container,可以用高阶函数封装一层传参,同时直接传入logging.getLogger("Dummy")的单例结果即可,不需要引用未定义完成的Dummy类:
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 class Dummy: logger = logging.getLogger("Dummy") # 用lambda封装一层,先传logger参数,再接收被装饰的方法 @lambda func: log_container(func, logger=logging.getLogger("Dummy")) def do_something(self): pass
方案2:改造装饰器支持带参数调用(灵活性更高)
如果后续需要频繁给不同类/方法指定不同logger,建议直接把装饰器改造成支持传参的形式,还可以适配从类实例动态取logger的场景:
import logging import functools from typing import Callable, Optional, Union def log_container(func: Optional[Callable] = None, *, logger: Optional[Union[logging.Logger, str]] = None): def decorator(_func: Callable): @functools.wraps(_func) def wrapper(*args, **kwargs): used_logger = logger # 如果传入的是字符串,自动从实例self中取对应属性作为logger if isinstance(used_logger, str): self = args[0] used_logger = getattr(self, used_logger) elif used_logger is None: used_logger = logging.getLogger("default") used_logger.info(f"{_func.__qualname__} started.") result = _func(*args, **kwargs) used_logger.info(f"{_func.__qualname__} ended.") return result return wrapper # 适配不带参数的装饰器用法 @log_container return decorator if func is None else decorator(func)
改造后的装饰器可以直接在类中使用,支持直接传logger实例或者logger的属性名:
class Dummy: logger = logging.getLogger("Dummy") # 写法1:直接传logger实例 @log_container(logger=logging.getLogger("Dummy")) def do_something_1(self): pass # 写法2:传logger属性名,装饰器运行时自动从self取 @log_container(logger="logger") def do_something_2(self): pass
内容的提问来源于stack exchange,提问作者Farhood ET
相关产品推荐
相关产品推荐

