首页
技术小册
AIGC
面试刷题
技术文章
MAGENTO
云计算
视频课程
源码下载
PDF书籍
「涨薪秘籍」
登录
注册
第 13章 性能测量和大O算法分析
13.1 timeit模块
13.2 cProfile分析器
13.3 大O算法分析
13.4 大O阶
13.4.1 使用书架打比方描述大O阶
13.4.2 大O 测量的是最坏情况
13.5 确定代码的大O 阶
13.5.1 为什么低阶项和系数不重要
13.5.2 大O 分析实例
13.5.3 常见函数调用的大O 阶
13.5.4 一眼看出大O 阶
13.5.5 当n 很小时,大O并不重要,而n通常都很小
第 14章 项目实战
14.1 汉诺塔
14.1.1 汉诺塔输出
14.1.2 汉诺塔源代码
14.1.3 汉诺塔编写代码
14.2 四子棋
14.2.1 四子棋输出
14.2.2 四子棋源代码
14.2.3 四子棋编写代码
第 15章 面向对象编程和类
15.1 拿现实世界打比方:填写表格
15.2 基于类创建对象
15.3 创建一个简单的类——WizCoin
15.3.1 方法__init__()和self
15.3.2 特性
15.3.3 私有特性和私有方法
15.4 函数type()和特性__qualname__
15.5 非OOP 和OOP 的例子:井字棋
15.6 为现实世界设计类是一件难事儿
第 16章 面向对象编程和继承
16.1 继承的原理
16.1.1 重写方法
16.1.2 super()函数
16.1.3 倾向于组合而非继承
16.1.4 继承的缺点
16.2 函数isinstance()和issubclass()
16.3 类方法
16.4 类特性
16.5 静态方法
16.6 何时应该使用类和静态的面向对象特性
16.7 面向对象的行话
16.7.1 封装
16.7.2 多态性
16.8 何时不应该使用继承
16.9 多重继承
16.10 方法解析顺序
第 17章 Python 风格的面向对象编程:属性和魔术方法
17.1 属性
17.1.1 将特性转换为属性
17.1.2 使用setter 验证数据
17.1.3 只读属性
17.1.4 什么时候应该使用属性
17.2 Python 的魔术方法
17.2.1 字符串表示魔术方法
17.2.2 数值魔术方法
17.2.3 反射数值魔术方法
17.2.4 原地魔术方法
17.2.5 比较魔术方法
当前位置:
首页>>
技术小册>>
Python编程轻松进阶(五)
小册名称:Python编程轻松进阶(五)
### 17.1.2 使用Setter验证数据 在Python编程中,随着项目规模的扩大和复杂度的提升,确保数据的有效性和安全性变得至关重要。Python的面向对象编程(OOP)特性提供了丰富的机制来实现这一目标,其中`setter`方法是一种非常有效的手段,用于在对象属性赋值时进行数据验证和预处理。本章节将深入探讨如何使用`setter`方法来验证数据,确保对象的状态符合预期,从而提高程序的健壮性和可维护性。 #### 17.1.2.1 理解Setter方法 在Python的类定义中,`setter`是与属性相关联的特殊方法,用于拦截对属性的赋值操作。通过定义`setter`,我们可以编写自定义的逻辑来验证或转换即将赋给属性的值。这是封装(Encapsulation)原则的一个重要应用,它允许我们隐藏对象的内部表示,并通过公共接口(如`setter`)来安全地访问和修改这些内部状态。 #### 17.1.2.2 使用`@property`装饰器定义Setter 在Python中,`@property`装饰器通常用于将类的方法伪装成属性,以便可以像访问普通属性一样调用它们,无需使用括号。同样,`@<property名>.setter`装饰器则用于定义与`@property`装饰的方法相关联的`setter`方法。 ```python class Person: def __init__(self, name, age): self._name = name self._age = age @property def name(self): return self._name @name.setter def name(self, value): if not isinstance(value, str): raise ValueError("Name must be a string") self._name = value @property def age(self): return self._age @age.setter def age(self, value): if not isinstance(value, int) or value < 0: raise ValueError("Age must be a non-negative integer") self._age = value # 使用示例 person = Person("Alice", 30) print(person.name) # Alice person.name = "Bob" # 正确 print(person.name) # Bob # 尝试设置非法值 try: person.age = -5 except ValueError as e: print(e) # Age must be a non-negative integer ``` 在上述例子中,`Person`类通过`@property`和`@<property名>.setter`装饰器定义了两个属性`name`和`age`,并在它们的`setter`方法中加入了类型检查和值范围检查。这确保了任何尝试为这些属性赋值时都会先通过验证,不符合条件的赋值操作将引发`ValueError`异常。 #### 17.1.2.3 复杂验证逻辑的实现 在实际应用中,数据的验证逻辑可能远比上述示例复杂。例如,你可能需要验证电子邮件地址的格式、检查电话号码是否属于特定地区、或者验证密码是否符合特定的安全要求(如长度、包含特殊字符等)。对于这些情况,可以在`setter`方法中调用专门的验证函数或使用正则表达式等工具来实现复杂的验证逻辑。 ```python import re def validate_email(email): pattern = r'^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$' if not re.match(pattern, email): raise ValueError("Invalid email format") class User: def __init__(self, email): self._email = None self.email = email # 调用email的setter进行验证 @property def email(self): return self._email @email.setter def email(self, value): validate_email(value) # 调用自定义验证函数 self._email = value # 使用示例 try: user = User("invalid-email") except ValueError as e: print(e) # Invalid email format user = User("user@example.com") print(user.email) # user@example.com ``` #### 17.1.2.4 链式Setter调用和状态一致性 在复杂对象中,属性的赋值可能相互依赖,一个属性的改变可能需要同时更新其他相关属性以保持对象状态的一致性。在这种情况下,`setter`方法可以执行更复杂的逻辑,包括调用其他`setter`方法或执行其他状态更新操作。 ```python class Account: def __init__(self, balance=0): self._balance = balance @property def balance(self): return self._balance @balance.setter def balance(self, value): if value < 0: raise ValueError("Balance cannot be negative") if self._balance > 0 and value == 0: # 假设当余额从正变为0时,需要执行某些操作,如发送通知 print("Balance is now zero.") self._balance = value # 使用示例 account = Account(100) account.balance = 50 # 正常更新 account.balance = 0 # 触发特殊操作 try: account.balance = -10 # 尝试设置非法值 except ValueError as e: print(e) # Balance cannot be negative ``` #### 17.1.2.5 小结 通过使用`setter`方法进行数据验证,Python类可以更加安全地管理其内部状态,防止因外部输入错误而导致的错误或异常。这不仅提高了程序的健壮性,还使得类的设计更加清晰和易于维护。在定义`setter`方法时,应考虑数据的类型、范围、格式等验证需求,并可以调用专门的验证函数或使用正则表达式等工具来实现复杂的验证逻辑。此外,还应注意维护对象状态的一致性,确保在属性赋值时能够正确地更新相关状态。
上一篇:
17.1.1 将特性转换为属性
下一篇:
17.1.3 只读属性
该分类下的相关小册推荐:
Python合辑1-Python语言基础
Python机器学习实战
Python合辑2-字符串常用方法
剑指Python(万变不离其宗)
Python甚础Django与爬虫
Python数据分析与挖掘实战(下)
Python高性能编程与实战
Python合辑13-面向对象编程案例(上)
Python自动化办公实战
Python编程轻松进阶(三)
Python合辑3-字符串用法深度总结
Python合辑11-闭包函数