python面向对象高级编程:使用@property

在Python的面向对象编程中,@property 是一个内置的装饰器,它允许将类的方法当作属性来访问。这种机制使得可以对属性的获取(getter)和设置(setter)进行细粒度的控制,同时保持属性访问的简洁性。

基本用法

@property 装饰器通常用于将一个方法转换为只读属性。如果还需要控制属性的设置,可以使用 @<属性名>.setter 装饰器。

示例:只读属性
复制代码

python复制代码

|---|---------------------------------------------------------|
| | class Circle: |
| | def __init__(self, radius): |
| | self._radius = radius # 私有属性,通常使用单下划线或双下划线前缀来表示 |
| | |
| | @property |
| | def radius(self): |
| | """获取圆的半径""" |
| | return self._radius |
| | |
| | @property |
| | def diameter(self): |
| | """获取圆的直径,只读""" |
| | return self._radius * 2 |
| | |
| | @property |
| | def area(self): |
| | """获取圆的面积,只读""" |
| | return 3.14159 * self._radius ** 2 |
| | |
| | # 创建一个 Circle 实例 |
| | c = Circle(5) |
| | |
| | # 访问只读属性 |
| | print(c.radius) # 输出: 5 |
| | print(c.diameter) # 输出: 10.0 |
| | print(c.area) # 输出: 78.53975 |
| | |
| | # 尝试设置只读属性(会报错) |
| | # c.radius = 10 # AttributeError: can't set attribute |

示例:带有setter的属性
复制代码

python复制代码

|---|-----------------------------------------------------------|
| | class CircleWithSetter: |
| | def __init__(self, radius): |
| | self._radius = radius |
| | |
| | @property |
| | def radius(self): |
| | return self._radius |
| | |
| | @radius.setter |
| | def radius(self, value): |
| | if value < 0: |
| | raise ValueError("Radius cannot be negative") |
| | self._radius = value |
| | |
| | # 创建一个 CircleWithSetter 实例 |
| | c = CircleWithSetter(5) |
| | |
| | # 访问和设置属性 |
| | print(c.radius) # 输出: 5 |
| | c.radius = 10 # 设置新的半径 |
| | print(c.radius) # 输出: 10 |
| | |
| | # 尝试设置非法的半径值(会报错) |
| | # c.radius = -1 # ValueError: Radius cannot be negative |

使用场景

  • 封装:隐藏对象的内部实现细节,只暴露必要的接口时。
  • 验证:需要在设置属性值时执行验证逻辑时。
  • 只读属性:某些属性只能被读取而不能被修改时。
  • 懒加载:第一次访问属性时才计算其值时。

注意

  • 使用 @property 可以使代码更加清晰和易于理解。
  • 不要滥用 @property,用于逻辑上应该是属性的东西,而不是用于所有方法。
  • 如果在类中使用了 @property,并且还需要一个对应的setter方法,请确保同时提供 @<属性名>.setter。
  • 虽然 @property 提供了对属性访问的细粒度控制,但它也增加了代码的复杂性。在简单的情况下,直接使用普通的属性可能更为合适。
相关推荐
不是万能的豆学长9 小时前
filetidy 文件整理助手:一键归类 + 规范重命名(Python 零依赖单文件工具)
大数据·开发语言·python·技术美术
gCode Teacher 格码致知10 小时前
Pandas教学-18:number与numeric的区别
python·pandas
梦想不只是梦与想13 小时前
Python 中subprocess 模块:执行外部命令
python·subprocess·调用外部命令
懂点Tech13 小时前
ctfshow MISC入门图片篇(信息附加):misc41解题思路
开发语言·python
catchadmin14 小时前
PHP 8.7 协程新提案 让跨协程代码共享请求身份
开发语言·php
念何架构之路15 小时前
go-grpc设计思想
开发语言·后端·golang
酷炫码神16 小时前
Day 10|Pinia 状态管理:把散落在各组件的数据,收进一个全局仓库
android·开发语言·javascript
Elastic 中国社区官方博客16 小时前
我们如何通过 70 多个拉取请求,将 OpenTelemetry Java agent 迁移到 invokedynamic
java·大数据·开发语言·elasticsearch·搜索引擎·全文检索·es
tyn18817 小时前
记录本地安装nacos服务的方法及异常
java·开发语言
步行cgn17 小时前
Spring MVC 视图机制的核心接口与类
java·开发语言·后端·spring·mvc