Python|PyCharm 调用装饰后的实例方法警告 Parameter ‘self‘ unfilled 的处理方法

文章讨论了在使用PyCharm时遇到的一个问题,即调用装饰器装饰的实例方法时出现Parameterselfunfilled警告。作者认为这是PyCharm的一个bug,并提供了三种解决方案:1)使用PEP-484类型注解来标注装饰器返回值为Callable;2)添加docstring来明确返回值类型;3)不推荐地,通过修改函数参数来规避警告。最后,作者推荐使用类型注解作为首选解决方案。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

警告原因

当调用装饰器装饰的实例方法时,PyCharm 会警告 Parameter 'self' unfilled;这可能是因为 PyCharm 未将装饰器装饰的实例方法视作实例方法,导致误判。我认为这是一个 PyCharm 的一个 Bug,可以在官网的 Bug 反馈中反馈这个问题:https://youtrack.jetbrains.com/issues

警告样例
def once_per_instance(method):
    """保证每个实例中方法只能被调用一次的装饰器"""

    @wraps(method)
    def wrapper(self, *args, **kwargs):
        # 在实例中,增加 _already_visited_instances 属性,用于统计哪些方法已被调用
        if "_already_visited_instances" not in self.__dict__:
            self.__dict__["_already_visited_instances"] = set()
        if method.__name__ not in self.__dict__["_already_visited_instances"]:
            self.__dict__["_already_visited_instances"].add(method.__name__)
            return method(self, *args, **kwargs)
        raise ValueError(f"instance method {method.__name__} can only be called once")

    return wrapper


if __name__ == "__main__":
    class TestClass:
        @once_per_instance
        def test_method(self):
            pass


    test_instance = TestClass()
    test_instance.test_method()  # 这里警告: Parameter 'self' unfilled
    test_instance.test_method()  # 这里警告: Parameter 'self' unfilled
解决方法 1(推荐):使用 PEP-484 规范,标注返回值类型,将装饰器返回值标记为 Callable 类型
def once_per_instance(method: Callable) -> Callable:
    """保证每个实例中方法只能被调用一次的装饰器"""

    @wraps(method)
    def wrapper(self, *args, **kwargs):
        # 在实例中,增加 _already_visited_instances 属性,用于统计哪些方法已被调用
        if "_already_visited_instances" not in self.__dict__:
            self.__dict__["_already_visited_instances"] = set()
        if method.__name__ not in self.__dict__["_already_visited_instances"]:
            self.__dict__["_already_visited_instances"].add(method.__name__)
            return method(self, *args, **kwargs)
        raise ValueError(f"instance method {method.__name__} can only be called once")

    return wrapper
解决方法 2(推荐):添加 docstring,将装饰器返回值标记为 Callable 类型
def once_per_instance(method: Callable) -> Callable:
    """保证每个实例中方法只能被调用一次的装饰器

    Parameters
    ----------
    method : Callable
        待装饰的实例方法

    Returns
    -------
    wrapper : Callable
        被装饰的实例方法
    """

    @wraps(method)
    def wrapper(self, *args, **kwargs):
        # 在实例中,增加 _already_visited_instances 属性,用于统计哪些方法已被调用
        if "_already_visited_instances" not in self.__dict__:
            self.__dict__["_already_visited_instances"] = set()
        if method.__name__ not in self.__dict__["_already_visited_instances"]:
            self.__dict__["_already_visited_instances"].add(method.__name__)
            return method(self, *args, **kwargs)
        raise ValueError(f"instance method {method.__name__} can only be called once")

    return wrapper
解决方法 3(不推荐):删掉 self 形参,改为使用 args[0]

这个严重违反 Python 社区规范,非常不推荐。

def once_per_instance(method):
    """保证每个实例中方法只能被调用一次的装饰器"""

    @wraps(method)
    def wrapper(*args, **kwargs):
        self = args[0]
        # 在实例中,增加 _already_visited_instances 属性,用于统计哪些方法已被调用
        if "_already_visited_instances" not in self.__dict__:
            self.__dict__["_already_visited_instances"] = set()
        if method.__name__ not in self.__dict__["_already_visited_instances"]:
            self.__dict__["_already_visited_instances"].add(method.__name__)
            return method(*args, **kwargs)
        raise ValueError(f"instance method {method.__name__} can only be called once")

    return wrapper
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

长行

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值