Descriptor未触发且无预期输出:MaxLength描述符实现问题排查
问题分析与修复:MaxLength描述符的错误使用
你的代码存在几个核心问题,导致描述符未按预期生效:
- 描述符必须定义为类属性才能触发
__get__/__set__方法,你把MaxLength实例赋值给了self._max_length(实例属性),所以访问limited_str.max_length只会返回描述符对象本身,不会调用__get__ value属性完全没关联到MaxLength描述符,赋值时自然不会触发长度校验max_length的setter逻辑混乱,完全没起到修改最大长度的作用
修正后的代码
class MaxLength: def __init__(self, max_length): self.max_length = max_length # 用字典存储每个实例的实际值,避免不同实例共享数据 self.instance_values = {} def __get__(self, instance, owner): # 返回实例存储的实际值 return self.instance_values.get(instance, "") def __set__(self, instance, value): if not isinstance(value, str): raise ValueError("Value must be a string") if len(value) > self.max_length: raise ValueError(f"String length exceeds the maximum length of {self.max_length}") # 保存合法值到实例专属存储 self.instance_values[instance] = value class LimitedString: # 把描述符定义为类属性,传入初始最大长度 value = MaxLength(10) def __init__(self, initial_value, max_length): # 初始化时修改描述符的max_length self.value.__init__(max_length) # 赋值初始值,触发描述符的__set__校验 self.value = initial_value @property def max_length(self): return self.value.max_length @max_length.setter def max_length(self, new_max): # 修改描述符的最大长度限制 self.value.max_length = new_max # 测试 limited_str = LimitedString("Short", 10) print(limited_str.max_length) # 输出10 print(limited_str.value) # 输出"Short" # 触发长度校验报错 try: limited_str.value = "Too long string" except ValueError as e: print(e) # 输出"String length exceeds the maximum length of 10" # 修改最大长度后可以赋值更长的字符串 limited_str.max_length = 20 limited_str.value = "This is a longer string now" print(limited_str.value) # 输出该字符串
关键改动说明
- 描述符改为类属性:
LimitedString里的value是类属性,关联MaxLength描述符,这样对实例的value进行读写时,会自动触发__get__和__set__ - 实例值存储:描述符里用
instance_values字典存储每个实例的实际字符串值,避免多个实例共享同一值的问题 - max_length属性关联:通过
@property直接读取描述符的max_length,setter直接修改描述符的最大长度限制 - 初始化逻辑修正:实例化时先修改描述符的max_length,再赋值初始值,确保初始值也经过校验
内容的提问来源于stack exchange,提问作者munish
相关产品推荐
相关产品推荐

