Python中检测到重复属性时如何触发DupError异常?
问题分析与解决方案
原代码问题
- 直接赋值私有属性绕过setter:原
__init__里直接给self._attribute赋值,完全没触发@attribute.setter装饰的方法,setter里的重复值检查逻辑根本没运行,自然不会抛出DupError。 - 实例添加时机错误:
Test.list_test.append(self)放在try-except块外部,不管属性值是否重复,都会把当前实例加入列表,这会导致后续检查出现错误的重复判定。
你觉得添加self.attribute = attribute是“绕开_attribute设计”其实是误解——_attribute作为私有属性(Python约定俗成的命名规范),本来就应该通过@property的setter方法来修改,直接操作_attribute才是违背了@property的封装意图。
正确修正方案
class DupError(Exception): pass class Test: list_test = [] def __init__(self, attribute): try: # 调用公开属性的setter,触发重复检查逻辑 self.attribute = attribute # 仅当属性设置成功(无异常)时,才将实例加入列表 Test.list_test.append(self) except DupError as e: msg = ' '.join(e.args) message = f'{e.__class__.__name__}: {msg}' print(message) @property def attribute(self): return self._attribute @attribute.setter def attribute(self, x): # 遍历已有实例,检查属性值是否重复 for instance in Test.list_test: if instance.attribute == x: raise DupError('属性值重复!') # 检查通过后,给私有属性赋值 self._attribute = x t1 = Test('g') t2 = Test('h') # 此处会触发DupError并打印异常信息 t3 = Test('g')
修正关键点
- 移除直接赋值
self._attribute的操作,通过self.attribute = attribute触发setter的重复检查,符合@property的封装设计。 - 将
Test.list_test.append(self)移入try块内,确保只有合法的实例才会被加入列表,避免后续检查出错。 - 优化setter里的遍历变量名,语义更清晰。
内容的提问来源于stack exchange,提问作者mtom
相关产品推荐
相关产品推荐

