Python描述符搭配装饰器做类型检查报__get__参数错误如何修复?
报错原因
Python描述符协议要求__get__方法必须接收3个参数,签名为__get__(self, instance, owner),各参数含义如下:
self:描述符类自身的实例instance:访问描述符属性的类实例,通过类直接访问属性时该值为Noneowner:描述符属性所属的类
你当前只定义了2个参数,Python调用时自动传入3个参数,就会触发参数数量不匹配的报错。
修复方法
补全__get__方法的第三个参数即可,用不到的话可以直接用占位符命名。另外你当前的实现把属性值存在描述符实例上,会导致所有MyClass的实例共享同一个值,建议改为把值存在对应类实例上,避免实例间数据冲突。
修复后的完整代码如下:
# 描述符定义 class PositiveNumber: def __get__(self, obj, owner): # 从类实例上取值,避免多实例共享 return obj._value def __set__(self, obj, value): if not isinstance(value, (int, float)): raise TypeError('value must be a number') if value < 0: raise ValueError('Value cannot be negative.') # 把值存在当前类实例上 obj._value = value # 装饰器定义 def positive_number(attr): def decorator(cls): setattr(cls, attr, PositiveNumber()) return cls return decorator # 实际执行类型校验的类 @positive_number('number') class MyClass(object): def __init__(self, value): self.number = value def main(): a = MyClass(3) print(a.number) if __name__ == '__main__': main()
如果你不需要支持多实例,只是要解决当前报错,只需要把__get__的签名改成def __get__(self, obj, _):即可,其他代码不用改。
内容的提问来源于stack exchange,提问作者Al_P
相关产品推荐
相关产品推荐

