Python中@property、setter与deleter的使用详解及矩形类示例

键盘旁的猫
键盘旁的猫
发布时间:2026-10-16 | 3人浏览过
原创

本文通过矩形类示例,详细讲解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内容,请搜索本站以往文章或继续浏览后续相关文章,感谢大家的支持!

相关标签:

本站声明

本文内容仅供参考,不代表本站观点。转载或引用请注明出处。如发现内容问题,请通过联系我们页面反馈。

Python 相关产品和应用

全部下载

专题列表