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

用类编写Python装饰器时PyCharm提示Unexpected argument是其bug吗

问题描述

我在使用类编写带参数的Python装饰器时遇到问题,对应异常提示截图如下:
PyCharm Unexpected argument 提示截图

复现代码

class Delay:
    def __init__(self, sec):
        self.sec = sec

    def __call__(self, func):
        self.func = func
        return self.wrapper

    def wrapper(self, *args, **kwargs):
        import time
        time.sleep(self.sec)
        result = self.func(*args, **kwargs)
        return result

@Delay(2)
def myfunc(n):
    return n * 2


if __name__ == '__main__':
    print(myfunc(6))

上述代码实际运行可正常输出结果,但PyCharm在myfunc(6)调用位置提示Unexpected argument错误,请问该提示是否为PyCharm本身的bug导致?

解答

这个提示不是PyCharm的bug,属于静态检查对当前写法的签名推断偏差,同时你写的装饰器本身也存在潜在问题:

  • 触发提示的原因:__call__返回的是绑定到Delay实例的self.wrapper方法,PyCharm做静态分析时,会把这个绑定方法识别为无额外显式入参的方法(实例方法的self参数在绑定时已经隐式传入,静态检查没识别到方法内部定义的*args, **kwargs可变参数),因此判定你传入参数6是多余的。
  • 额外隐患:当前写法如果用同一个Delay实例装饰多个函数,self.func属性会被最后一个被装饰的函数覆盖,之前装饰的函数执行时会调用错误的逻辑。

最稳妥的修复方式是把包装函数改成__call__内部的嵌套函数,同时用functools.wraps保留原函数元信息,改完之后PyCharm可以正确识别函数签名,也能解决多函数装饰的覆盖问题:

import time
from functools import wraps

class Delay:
    def __init__(self, sec):
        self.sec = sec

    def __call__(self, func):
        @wraps(func)
        def wrapper(*args, **kwargs):
            time.sleep(self.sec)
            return func(*args, **kwargs)
        return wrapper

@Delay(2)
def myfunc(n):
    return n * 2

if __name__ == '__main__':
    print(myfunc(6))

如果暂时不想调整代码结构,也可以通过给wrapper补充类型注解的方式让PyCharm识别参数,但这种方式解决不了func被覆盖的问题,不推荐在生产环境使用。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.29 08:27:03