文章内容如有错误或排版问题,请提交反馈,非常感谢!
@property装饰器简介
在Python中,@property装饰器是一种优雅的属性管理工具,它允许你将类的方法伪装成属性(即无需使用()调用),同时可以在属性访问时添加逻辑(如数据校验、动态计算等)。

@property 的核心作用
- 隐藏实现细节:对外暴露属性式的访问接口,内部可封装复杂逻辑。
- 控制属性访问:在读取、设置或删除属性时触发自定义逻辑(如数据校验)。
- 兼容性:允许在不破坏现有代码的前提下修改内部实现。
基本用法:定义属性的读写删除
定义属性的读取(getter)
使用@property装饰器将一个方法转换为”属性读取”方法:
class Person:
def __init__(self, name):
self._name = name # 实际存储的属性(通常用下划线命名)
@property
def name(self):
print("Getting name")
return self._name
# 使用
p = Person("Alice")
print(p.name) # 输出: Getting name→Alice
定义属性的设置(setter)
使用@属性名.setter装饰器定义属性的设置逻辑:
class Person:
def __init__(self, name):
self._name = name
@property
def name(self):
return self._name
@name.setter
def name(self, value):
if not isinstance(value, str):
raise ValueError("Name must be a string!")
print("Setting name")
self._name = value
# 使用
p = Person("Alice")
p.name = "Bob" # 正常设置
p.name = 123 # 抛出 ValueError
定义属性的删除(deleter)
使用@属性名.deleter装饰器定义删除逻辑:
class Person:
def __init__(self, name):
self._name = name
@property
def name(self):
return self._name
@name.deleter
def name(self):
print("Deleting name")
del self._name
# 使用
p = Person("Alice")
del p.name # 输出: Deleting name
典型应用场景
数据校验
禁止非法值被设置:
class Circle:
def __init__(self, radius):
self.radius = radius # 通过 setter 设置
@property
def radius(self):
return self._radius
@radius.setter
def radius(self, value):
if value <= 0:
raise ValueError("Radius must be positive")
self._radius = value
动态计算属性
属性值由其他属性动态计算得出:
class Rectangle:
def __init__(self, width, height):
self.width = width
self.height = height
@property
def area(self):
return self.width * self.height # 每次访问时计算
# 使用
rect = Rectangle(3, 4)
print(rect.area) # 输出: 12
rect.width = 5
print(rect.area) # 输出: 20 (自动更新)
属性访问控制
限制某些属性为只读:
class User:
def __init__(self, user_id):
self._user_id = user_id
@property
def user_id(self):
return self._user_id # 无 setter,无法修改
# 使用
user = User(1001)
user.user_id = 2002 # 抛出 AttributeError: can't set attribute
深入原理
- 属性本质:@property创建了一个 property 对象,管理属性的 get、set、delete 方法。
- 描述符协议:property实现了描述符协议,通过 __get__、__set__ 和 __delete__ 方法拦截属性操作。
注意事项
- 避免副作用:Getter方法尽量不修改对象状态。
- 性能考量:频繁计算的属性可考虑缓存结果。
- 命名冲突:属性名不要与实例变量同名(如用 _name 存储数据,name 作为属性)。



