如何使用装饰器检查类属性的初始化?
问题修复:类初始化方法的装饰器参数检查错误
错误根源
你的代码存在三个核心问题:
__init__方法缺少self参数:类的实例方法必须以self作为第一个参数,否则无法绑定到实例对象。- 装饰器使用方式错误:你定义的
check是带参数的装饰器工厂,直接用@check装饰时,Python会把__init__函数传给check的data参数,完全偏离了你要检查初始化参数的需求。 - 装饰器逻辑错位:原装饰器检查的是装饰器工厂接收的固定值,而非实例化时传入的
data参数。
基础修复版本
如果你只需要检查__init__的data参数是否在指定列表里,用普通装饰器即可:
def check(func): def wrapper(self, data, *args, **kwargs): if data not in ["toto", "tata"]: raise ValueError("Wrong argument") return func(self, data, *args, **kwargs) return wrapper class Foo: @check def __init__(self, data): self.data = data # 测试用例 Foo("toto") # 正常运行 # Foo("t") # 抛出 ValueError: Wrong argument
通用可配置版本
如果需要让装饰器支持检查不同参数、自定义允许值,可以改成带参数的装饰器工厂:
def check_param(param_name, allowed_values): def decorator(func): def wrapper(self, *args, **kwargs): # 优先获取关键字参数,再匹配位置参数 if param_name in kwargs: value = kwargs[param_name] else: # 找到参数在函数签名中的位置(排除self) param_idx = func.__code__.co_varnames.index(param_name) - 1 if param_idx >= len(args): raise TypeError(f"Missing required parameter: {param_name}") value = args[param_idx] if value not in allowed_values: raise ValueError(f"Invalid {param_name}: {value}. Allowed values: {allowed_values}") return func(self, *args, **kwargs) return wrapper return decorator class Foo: @check_param(param_name="data", allowed_values=["toto", "tata"]) def __init__(self, data): self.data = data # 测试用例 Foo(data="tata") # 正常运行 # Foo(data="t") # 抛出 ValueError: Invalid data: t. Allowed values: ['toto', 'tata']
原错误的详细解释
当你用@check装饰__init__时,Python实际执行的是:
__init__ = check(__init__)
此时check的data参数接收的是__init__函数,返回decorator函数。当你实例化Foo(data="t")时,Python会调用decorator(data="t"),但decorator只接受一个参数(被装饰的函数),因此触发TypeError: decorator() got an unexpected keyword argument 'data'。
内容的提问来源于stack exchange,提问作者Mistapopo
相关产品推荐
相关产品推荐

