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 可以增强类的封装性,使得数据的获取和设置更加灵活和安全。

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

相关推荐
一入JAVA毁终身11 分钟前
处理Lombok的一个小BUG
java·开发语言·bug
费弗里18 分钟前
Python全栈应用开发利器Dash 3.x新版本介绍(2)
python·dash
Hellyc33 分钟前
JAVA八股文:异常有哪些种类,可以举几个例子吗?Throwable类有哪些常见方法?
java·开发语言
吴佳浩36 分钟前
Python入门指南-AI番外-MCP完整教程:从零开始学会Model Context Protocol
人工智能·python·mcp
加油吧zkf1 小时前
目标检测新纪元:DETR到Mamba实战解析
图像处理·人工智能·python·目标检测·分类
2301_803554521 小时前
c++中的绑定器
开发语言·c++·算法
海棠蚀omo1 小时前
C++笔记-位图和布隆过滤器
开发语言·c++·笔记
杰哥技术分享1 小时前
Yii2 安装-yii2-imagine
开发语言·yii
程序员阿超的博客1 小时前
Python 数据分析与机器学习入门 (五):Matplotlib 数据可视化基础
python·信息可视化·数据分析·matplotlib·数据可视化·python教程·pyplot
站大爷IP2 小时前
Python 办公实战:用 python-docx 自动生成 Word 文档
python