在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
提供了对属性访问的细粒度控制,但它也增加了代码的复杂性。在简单的情况下,直接使用普通的属性可能更为合适。