Python 面向对象编程 —— 属性的装饰器:@property 和 @setter

Python 面向对象编程 ------ 属性的装饰器:@property@setter

在 Python 中,@property@setter 装饰器用于控制类属性的访问和赋值。它们能够帮助我们创建具有getter和setter功能的属性,同时保留类的封装性。

  • Getter 是一个方法,用于 获取对象的属性值;它通常是只读的,不会修改对象的属性,只是返回属性的当前值。
  • 通过 getter 方法,外部代码可以间接访问对象的属性,即使这些属性是私有的(以 ___ 开头)。
  • Setter 是一个方法,用于 设置对象的属性值;它通常会对传入的值进行验证或处理,然后将其赋给对象的属性。
  • 通过 setter 方法,外部代码可以修改对象的属性,但 setter 方法可以对赋值过程进行控制,比如限制值的范围,或处理一些特殊逻辑。

1. @property 装饰器

@property 装饰器将一个方法转化为属性,使得方法可以像属性一样被访问。

作用:
  • @property 装饰器将方法转换为属性,使得方法可以像访问普通属性一样被调用。
  • 用于将方法封装成只读属性,控制外部对某个属性的读取行为。
使用场景:
  • 在需要计算一个值的时候,使用@property可以避免每次访问时都调用一个函数。
  • 通过@property,你可以限制类外部的写入操作,仅允许对特定属性进行控制和修改。
语法实例:
python 复制代码
class 类名:

    @property
    def 方法名(self):
        方法代码

在需要将方法变成属性的上面写@property即可将方法变成属性

代码示例:
python 复制代码
class Circle:
    def __init__(self, radius):
        self.radius = radius  

    @property
    def radius_attribute(self):
        return self.radius
    
    #@property
    def area(self):
        return 3 * self.radius
    
circle = Circle(5)
print(circle.radius_attribute)
print(circle.area()) 
输出示例:
复制代码
5
15
解释:
  • circle = Circle(5):实例一个对象,传入参数5,并赋值给circle变量
  • print(circle.radius_attribute):访问radius_attribute属性,因为添加了@property装饰器,它就从方法变成了属性
  • print(circle.area()) :调用area方法,但没添加就@property装饰器就正常调用

2. @setter 装饰器

@setter 装饰器是与 @property 配合使用的,用于设置属性值。当你通过属性赋值时,@setter 装饰器能够捕获赋值操作并定义相应的行为。

作用:
  • @setter 装饰器可以定义属性的设置规则,进行验证或修改值。
  • 它让你能够在对属性赋值时,执行一些逻辑,控制哪些值可以被接受。
  • 可以把 @setter 看作是一种拦截器

使用场景:
  • 想要限制某个属性的值,比如限制范围或进行格式检查。
  • 需要在设置属性值时,执行额外的操作,如更新其他相关值。
示例语法:
python 复制代码
class 类名:
   
    #先设置将一个方法定义为属性
    @property
    def 方法名(self):
        代码
    
    
    @设置成属性的方法名.setter
    def 方法名(self, value):
        代码
示例代码(通过计算圆的直径为例子):
python 复制代码
class Circle:
    def __init__(self, radius):
        self._radius = radius  # 私有属性,避免直接访问

    @property
    def radius(self):
        """获取半径"""
        return self._radius

    @radius.setter
    def radius(self, value):
        """设置半径"""
        self._radius = value

    @property
    def diameter(self):
        """计算圆的直径"""
        return 2 * self._radius
    
# 示例代码
circle = Circle(5)
print(circle.radius)    # 通过 @property 装饰器,获取半径值,输出 5

circle.radius = 10      # 通过 `@radius.setter` 装饰器,半路拦截修改半径值为 10
print(circle.radius)    # 获取设置后的半径值,输出 10
print(circle.diameter)  # 通过 @property 获取直径值,输出 20
输出示例:
复制代码
5
10
20
解释:
  • @radius.setter:当你使用 @property 你使用 @property 装饰器将方法变成属性之后,你可能还希望给这个属性设置一个 setter 方法,以便修改属性的值。这个 setter 方法会在你对该属性进行赋值时自动调用

  • circle = Circle(5):实例一个对象,传入参数数字5,并赋值给circle变量

  • print(circle.radius): 通过 @property 装饰器,获取半径值,输出 5

  • circle.radius = 10:通过 @radius.setter 装饰器,半路拦截修改半径值为 10

  • print(circle.radius) :获取半路拦截修改半径值,输出 10

  • print(circle.diameter) :通过 @property 变成属性后,访问获取直径值,输出 20

这个过程就是将初始的值5修改为10,然后计算。


3. 结合使用 @property@setter

在实际开发中,我们常常将 @property@setter 一起使用,这样可以实现对属性值的完全控制,并同时提供更直观的接口。

示例代码:
python 复制代码
class BankAccount:
    # 初始化方法,接受一个初始余额并将其赋值给私有属性 _balance
    def __init__(self, balance):
        self._balance = balance  # 私有变量用于存储账户余额

    # 定义一个属性方法 (getter),返回当前余额
    @property
    def balance(self):
        return self._balance

    # 定义一个 setter 方法,用于设置余额。这里加入了负余额检查
    @balance.setter
    def balance(self, amount):
        # 如果传入的金额为负数,抛出异常
        if amount < 0:
            raise ValueError("余额不能为负数")
        self._balance = amount  # 更新余额

    # 存款方法,将指定金额添加到余额中
    def deposit(self, amount):
        self.balance += amount  # 使用 setter 更新余额

    # 取款方法,确保余额足够才能进行取款
    def withdraw(self, amount):
        # 如果取款金额大于当前余额,抛出异常
        if amount > self.balance:
            raise ValueError("余额不足")
        self.balance -= amount  # 使用 setter 更新余额

# 创建一个 BankAccount 对象,初始余额为 1000
account = BankAccount(1000)

# 输出当前余额,使用 getter 方法
print(account.balance)  # 输出 1000

# 存款 500 元,余额应该变为 1500
account.deposit(500)
print(account.balance)  # 输出 1500

# 通过 setter 方法直接设置余额为 2000
account.balance = 2000
print(account.balance)  # 输出 2000

# 下面的操作会抛出异常
# account.balance = -100  # 会抛出 ValueError: 余额不能为负数

总结

  • @property 让方法可以像属性一样被访问。
  • @setter 让你在给属性赋值时可以控制行为,并且实现数据验证、修改等功能。
  • 使用 @property@setter 可以增强类的封装性,使得数据的获取和设置更加灵活和安全。

通过这两个装饰器,你可以简化对属性的控制,提升代码的可读性和可维护性。

相关推荐
陈随易17 分钟前
一段时间没写文章了,花了10天放了个屁
前端·后端·程序员
星星电灯猴20 分钟前
抓包工具分析接口跳转异常:安全校验误判 Bug 全记录
后端
调试人生的显微镜21 分钟前
后台发热、掉电严重?iOS 应用性能问题实战分析全过程
后端
深栈解码30 分钟前
OpenIM 源码深度解析系列(十八):附录二数据库结构
后端
前端付豪36 分钟前
Google Ads 广告系统排序与实时竞价架构揭秘
前端·后端·架构
努力的小郑1 小时前
MySQL DATETIME类型存储空间详解:从8字节到5字节的演变
后端
哪吒编程2 小时前
我的第一个AI编程助手,IDEA最新插件“飞算JavaAI”,太爽了
java·后端·ai编程
二闹3 小时前
我为什么躺平?因为代码自己会“飞”呀!
spring boot·后端·运营
mortimer3 小时前
一次MySQL大表索引删除之旅:从卡死到表损坏再到迁移
数据库·后端·mysql
想用offer打牌3 小时前
一站式了解责任链模式
java·后端·设计模式·责任链模式