Python 中的 @property
特性详解
@property
是 Python 中用于将方法转换为属性的装饰器,它允许开发者以访问属性的方式调用方法,同时可以添加逻辑控制(如数据校验、计算属性等)。以下是其核心用法和优势:
一、@property
的基本用法
1. 将方法变为只读属性
class Circle:def __init__(self, radius):self.radius = radius@propertydef area(self): # 通过方法计算面积,但调用时像属性return 3.14 * self.radius ** 2c = Circle(5)
print(c.area) # 78.5(无需括号,像访问属性)
# c.area = 100 # 报错!area是只读属性
2. 添加 setter 和 deleter
通过 @属性名.setter
和 @属性名.deleter
控制属性的写入和删除:
class Temperature:def __init__(self, celsius):self._celsius = celsius # 内部存储摄氏度@propertydef celsius(self): # 读操作return self._celsius@celsius.setterdef celsius(self, value): # 写操作(可校验)if value < -273.15:raise ValueError("温度不能低于绝对零度")self._celsius = value@propertydef fahrenheit(self): # 计算属性(华氏度)return self._celsius * 9/5 + 32temp = Temperature(25)
print(temp.fahrenheit) # 77.0(自动计算)
temp.celsius = 30 # 通过 setter 修改
# temp.celsius = -300 # 触发 ValueError
二、@property
的核心优势
1. 数据校验
在 setter 中限制属性值的合法性:
class User:def __init__(self, name):self._name = name@propertydef name(self):return self._name@name.setterdef name(self, value):if not isinstance(value, str):raise TypeError("姓名必须是字符串")self._name = valueuser = User("Alice")
user.name = "Bob" # 合法
# user.name = 123 # 报错:TypeError
2. 计算属性
动态生成属性值(如面积、平均值):
class Rectangle:def __init__(self, width, height):self.width = widthself.height = height@propertydef area(self):return self.width * self.heightrect = Rectangle(3, 4)
print(rect.area) # 12(自动计算)
3. 兼容性
在不改变外部接口的情况下修改内部实现:
class OldClass:def __init__(self, value):self.value = value # 直接暴露属性# 改为使用 @property 后,外部代码无需修改
class NewClass:def __init__(self, value):self._value = value@propertydef value(self):return self._value * 2 # 内部逻辑变化
三、@property
与普通方法的区别
特性 | @property | 普通方法 |
---|---|---|
调用方式 | obj.property (无括号) | obj.method() (需括号) |
功能 | 像属性一样访问,但可包含逻辑 | 显式执行操作 |
可写性 | 需配合 setter 才能修改 | 可直接修改返回值 |
四、实际应用场景
1. 数据模型(如 Django ORM)
class Product:def __init__(self, price):self._price = price@propertydef price_with_tax(self):return self._price * 1.1 # 自动计算含税价格
2. API 设计
隐藏内部字段名,提供统一接口:
class APIResponse:def __init__(self, raw_data):self._raw_data = raw_data@propertydef data(self):return self._raw_data["data"] # 封装原始数据解析
3. 兼容旧代码
逐步替换直接暴露的属性:
class LegacyClass:def __init__(self, x):self.x = x # 旧代码直接访问 x# 新代码改用 @property
class ModernClass:def __init__(self, x):self._x = x@propertydef x(self):return self._x ** 2 # 新增逻辑
五、总结
要点 | 说明 |
---|---|
基本功能 | 将方法伪装成属性,保持调用简洁性 |
核心方法 | @property (读)、@attr.setter (写)、@attr.deleter (删) |
优势 | 数据校验、计算属性、接口兼容性 |
适用场景 | 需要控制属性访问或动态计算的场景 |
核心价值:
以属性的语法实现方法的功能,兼顾简洁性与灵活性。