Python中@property、setter与deleter的使用详解及矩形类示例
本文通过矩形类示例,详细讲解Python中@property、setter和deleter装饰器的使用方法。通过封装长宽属性,实现面积自动计算与只读控制,展示如何规范编写getter、setter及deleter函数,确保属性访问的安全性与逻辑一致性。
假设我们需要构建一个表示矩形的类,其核心属性包含矩形的长度和宽度。
接着,我们需要实现一个方法,用于计算该矩形的面积。
初始代码实现
"""__dict__属性:查看对象内部所有属性名和属性值组成的字典
在Python类的内部,无论是类属性还是实例属性,都是以字典的形式进行存储的,其中属性名作为键,而值作为该键对应的值。
"""
# 定义类
class Rect:
# 定义属性
def __init__(self, length=0, width=0):
self.length = length
self.width = width
self.area = length * width
# 定义方法
def area(self):
self.area = self.width * self.length
return self.area
# 创建一个长为4宽为5的矩形对象,计算面积
r1 = Rect(4, 5)
print(r1.area) # 20
# 直接修改矩形面积属性值
r1.area = 100
print(r1.__dict__) # {'length': 4, 'width': 5, 'area': 100}
# 修改矩形宽度以达到修改矩形面积的效果, 失败
r1.width = 111111
print(r1.area) # 100
print(r1.__dict__) # {'length': 4, 'width': 111111, 'area': 100}
# 修改矩形长度以达到修改矩形面积的效果,失败
r1.length = 9999999
print(r1.area) # 100
print(r1.__dict__) # {'length': 9999999, 'width': 10, 'area': 100}
print(Rect.__dict__)
print(r1.__dict__)上述代码虽然实现了根据长宽计算面积的功能,但存在逻辑缺陷:用户可以直接修改面积属性的值,而无需通过长宽计算,这不符合实际物理意义。此外,当长宽发生变化时,面积并未自动更新,导致数据不一致。
为解决这一问题,我们可以利用Python中的getter和setter机制来规范属性访问行为。
引入getter和setter的代码实现
@property是Python内置的装饰器,用于实现类似JavaBean的属性访问结构。当某个函数的主要目的是返回一个值时,可以使用@property装饰该函数,将其转换为同名的只读属性,即实现“getter”功能。
setter与deleter方法的使用要求:附加函数必须与原始属性名保持一致。必须先定义@property,才能定义后续的setter和deleter。特别注意,@property修饰的函数必须位于setter和deleter之前,且三者对应的函数名必须完全相同。
参考官方文档中关于@property的说明
# 注意:这里的getter、setter、deleter所修饰的函数名(func_area)的命名并不符合规范
# 只是为了更好的理解 “将函数转化为具有相同名称的属性” 这句话
# 正确的规范应该是 不带_ 的属性名
class Rect:
def __init__(self, length=0, width=0):
self.length = length
self.width = width
self._area = length * width # 为了规范需要设置成保护成员属性
# 定义getter对应的函数
@property # 需要@property装饰器
def func_area(self):
print("重新计算面积并赋值")
self._area = self.width * self.length
return self._area # @property修饰的函数需要一个返回值
# @func_area.setter # 需要 @函数名.setter 的装饰器
# def func_area(self, value):
# raise ValueError
@func_area.setter # 需要 @函数名.setter 的装饰器
def func_area(self, value):
self._area = value
@func_area.deleter
def func_area(self):
del self._area
r1 = Rect(4, 5)
print(r1.func_area) # 20
r1.width = 10
print(r1.func_area) # 40
r1.length = 20
print(r1.func_area) # 200
r1.func_area = 80
print(r1.__dict__) # {'length': 20, 'width': 10, '_area': 80}
del r1.func_area # 将调用 deleter
print(r1.__dict__) # {'length': 20, 'width': 10}
print(r1.func_area) # 200
print(r1.__dict__) # {'length': 20, 'width': 10, '_area': 200}
# r1.func_area = 80 # 报错:ValueError
getter与setter的实际应用场景
- getter的作用:在获取属性值(如面积)之前,若需执行其他操作(如根据长宽重新计算),则为该属性添加getter。
- setter的作用:在赋值属性(如面积)之前,若需执行验证或其他逻辑(如禁止直接修改面积并抛出ValueError),则为该属性添加setter。
如何正确添加getter和setter
getter的实现步骤
在待添加getter的属性名前添加_(遵循代码规范)。
定义与getter对应的函数。
- 该函数需使用
@property装饰器。 - 函数名应为去掉
_后的属性名。 - 函数必须包含返回值,即返回属性的实际值。
获取属性值的方式为:对象.去掉_后的属性名(本质是调用getter对应的函数,获取其返回值)。
setter的实现步骤
若需为属性添加setter,必须先为其添加getter。
首先完成getter的定义。
定义与setter对应的函数。
- 该函数需使用@getter函数名.setter装饰器。
- 函数名应为去掉
_后的属性名。 - 该函数需接收一个参数(用于赋值),且无需返回值,该参数即用于给属性赋值的值。
给属性赋值的方式为:对象.去掉_后的属性名 = 值(本质是调用setter对应的函数,通过参数对属性进行赋值)。
官方提供的规范代码示例
class C:
def __init__(self):
self._x = "zhangsan"
@property
def x(self):
"""I'm the 'x' property."""
return self._x
@x.setter
def x(self, value):
self._x = value
@x.deleter
def x(self):
del self._x
if __name__ == '__main__':
c = C()
# getter
print(c.x) # zhangsan
print(c.__dict__) # {'_x': 'zhangsan'}
# setter
c.x = "lisi"
print(c.__dict__) # {'_x': 'lisi'}
# deleter
del c.x
print(c.__dict__) # {}
至此,关于Python中getter、setter及deleter的使用示例讲解完毕。如需了解更多相关Python getter、setter、deleter内容,请搜索本站以往文章或继续浏览后续相关文章,感谢大家的支持!
免责声明:本文内容仅供参考,不代表本站观点。转载或引用请注明出处。









