You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Python中如何将类属性作为参数传递给类方法的装饰器?

问题解答

你的需求完全可以实现,你当前的写法存在两个问题:

  1. 你写的log_container装饰器本身不支持带参数调用,直接写@log_container(logger=xxx)会触发参数缺失错误
  2. 装饰器在类定义阶段就会执行,此时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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.28 08:24:03