为何Python类属性中的输入未触发断言异常?
问题根源与解决方案
为什么校验逻辑没触发?
Python中,@property装饰器定义的setter方法,只有通过实例.公开属性名 = 值的方式赋值时才会执行。你直接给_country_code、_country_name这类私有属性赋值,完全绕过了setter里的断言逻辑——因为Python的单下划线私有属性只是编码约定,并非真正的访问限制,外部代码可以直接读写。
解决方法
1. 严格通过公开属性赋值
修改调用代码,不要直接操作私有属性,而是使用setter对应的公开属性名:
# 正确调用方式(会触发setter校验) country = Country() country.country_code = "CN" # 会触发assert校验长度是否>3 country.country_name = "canada" # 会触发首字母大写后是否>'U'的校验
2. 强化属性封装(可选)
如果想进一步避免外部误操作私有属性,可以把属性名改成双下划线开头(比如__country_code),Python会自动对这类属性做名称修饰(实际存储为_Country__country_code),虽然不能完全阻止恶意访问,但能大幅降低误操作的概率,同时让代码的封装意图更明确:
class Country: def __init__(self): self.__country_code = "" self.__country_name = "" @property def country_code(self): return self.__country_code @country_code.setter def country_code(self, value): assert len(value) > 3, "Country code length must be >3" self.__country_code = value @property def country_name(self): return self.__country_name @country_name.setter def country_name(self, value): assert value[0].upper() > 'U', "First letter must be > 'U'" self.__country_name = value
3. 替换assert为主动抛出异常(更推荐生产环境)
assert在Python中可以通过-O选项被全局禁用,生产环境下建议直接使用raise抛出明确的异常,比如ValueError,确保校验逻辑不会失效:
@country_code.setter def country_code(self, value): if len(value) <= 3: raise ValueError("Country code length must be greater than 3") self.__country_code = value
内容的提问来源于stack exchange,提问作者Elliott2232
相关产品推荐
相关产品推荐

