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

Python类内装饰器遇两类报错,求助解决方案及私有属性访问问题

问题分析与解决

错误原因及修复方案

错误2:function '__s_operation' lacks a positional argument

你把__s_operation定义成了类的普通实例方法,但在类定义阶段装饰其他方法时,Python会尝试将类作为self参数传入装饰器,而装饰器只接收func一个参数,因此触发参数缺失错误。

修复:将__s_operation标记为静态方法,避免自动传入self参数:

import functools
import logging

logger = logging.getLogger(__name__)

class ClientHandler:
    def __init__(self, c_ident):
        self.__is_dead = False
        self.c_ident = c_ident  # 修正初始化参数,原代码未传入c_ident

    @staticmethod  # 添加静态方法装饰器,避免自动传入self
    def __s_operation(func):
        @functools.wraps(func)
        def check(*args, **kwargs):  # 兼容关键字参数
            self = args[0]
            if not self.__is_dead:
                return func(*args, **kwargs)  # 返回被装饰方法的返回值
            else:
                logger.error(
                    "couldn't proceed - client {} is dead!".format(
                        self.c_ident
                    )
                )
        return check

    @__s_operation
    def __receive_m(self, size) -> bytes:
        # 示例实现
        return b"received data"

    @__s_operation
    def close_c(self, message: str) -> None:
        # 示例实现
        print(f"Closing client: {message}")

错误1:'ClientHandler' object is not callable

这个错误是错误2的连锁反应:因为装饰器被当成实例方法,类定义时调用__s_operation会把ClientHandler类本身作为self传入,导致func参数被错误覆盖,后续调用被装饰方法时相当于尝试调用类对象,自然触发"不可调用"错误。修复错误2后,该问题会自动解决。

关于私有属性/方法的访问

在类内部定义的装饰器(包括嵌套的check函数)可以正常访问实例的私有属性(如__is_dead)和私有方法。Python的双下划线名称修饰机制只是防止外部类/实例直接访问,同一个类内部的代码不受限制。

额外优化点

  • 修正__init__方法,补充c_ident参数传入逻辑
  • 装饰器的check函数添加**kwargs,兼容被装饰方法的关键字参数
  • 被装饰方法有返回值时,check函数需返回func(*args, **kwargs)的结果,否则调用方法会得到None

内容的提问来源于stack exchange,提问作者good user

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.12 20:22:15