Python中的@property装饰器有什么作用 如何使用它保护属性

来源:PHP编程网作者:北京GEO公司头衔:草根站长
导读:本期聚焦于小伙伴创作的《Python中的@property装饰器有什么作用 如何使用它保护属性》,敬请观看详情,探索知识的价值。以下视频、文章将为您系统阐述其核心内容与价值。如果您觉得《Python中的@property装饰器有什么作用 如何使用它保护属性》有用,将其分享出去将是对创作者最好的鼓励。

在Python面向对象编程中,类的属性如果直接暴露给外部,很容易被赋上不符合预期的值,比如年龄被设置为负数、成绩超过满分上限等。@property装饰器就是用来解决这类问题的工具,它可以将类的方法转换为类似属性的访问方式,同时支持对属性的读取、修改、删除逻辑进行自定义控制。

@property装饰器的核心作用

@property装饰器的主要作用有两个,一是让方法可以像属性一样被调用,简化代码的访问逻辑,二是通过自定义getter、setter、deleter方法,对属性的操作进行约束,实现属性的保护。

在没有使用@property的时候,如果我们想获取或修改一个需要校验逻辑的属性,通常需要定义get_xxx和set_xxx这样的方法,调用的时候需要加括号,不够直观。使用@property之后,我们可以把这些方法伪装成属性,调用的时候不需要加括号,和直接访问属性的体验一致,同时还能在背后执行校验逻辑。

@property的基础使用方法

使用@property装饰器需要配合对应的setter和deleter装饰器,分别对应属性的读取、修改、删除操作。下面通过一个简单的示例来展示基础用法。

定义只读属性

如果只需要获取属性的值,不需要修改,可以只使用@property装饰器定义getter方法。

class User:
    def __init__(self, name):
        self._name = name  # 下划线开头表示内部属性,不建议外部直接访问

    @property
    def name(self):
        # 定义name属性的getter方法,返回内部存储的值
        return self._name

# 创建实例
user = User("张三")
# 像访问属性一样调用name方法,不需要加括号
print(user.name)  # 输出:张三
# 尝试修改会报错,因为没有定义setter方法
# user.name = "李四"  # 会抛出AttributeError

定义可读可写的属性

如果需要支持修改属性,需要额外定义对应属性的setter方法,方法名和@property装饰的方法名一致,装饰器为@方法名.setter。

class User:
    def __init__(self, name, age):
        self._name = name
        self._age = age

    @property
    def age(self):
        # age属性的getter方法
        return self._age

    @age.setter
    def age(self, value):
        # age属性的setter方法,在这里可以添加校验逻辑
        if not isinstance(value, int):
            raise TypeError("年龄必须是整数")
        if value < 0 or value > 150:
            raise ValueError("年龄必须在0到150之间")
        self._age = value

# 创建实例
user = User("张三", 20)
print(user.age)  # 输出:20
# 合法修改
user.age = 25
print(user.age)  # 输出:25
# 非法修改会抛出对应异常
# user.age = -5  # 抛出ValueError: 年龄必须在0到150之间
# user.age = "二十"  # 抛出TypeError: 年龄必须是整数

定义可删除的属性

如果需要支持删除属性,可以再定义deleter方法,装饰器为@方法名.deleter。

class User:
    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 TypeError("姓名必须是字符串")
        self._name = value

    @name.deleter
    def name(self):
        # 删除属性时的逻辑,这里示例是将内部属性设为None
        print("删除姓名属性")
        self._name = None

user = User("张三")
print(user.name)  # 输出:张三
del user.name  # 输出:删除姓名属性
print(user.name)  # 输出:None

使用@property保护属性的实际场景

在实际开发中,@property最常见的用途就是对属性的赋值进行合法性校验,避免外部传入不符合要求的数据,下面是几个常见的场景示例。

场景1:限制属性取值范围

比如一个学生类,成绩属性只能在0到100之间,通过@property的setter方法就可以实现这个限制。

class Student:
    def __init__(self, score):
        self._score = score

    @property
    def score(self):
        return self._score

    @score.setter
    def score(self, value):
        if not isinstance(value, (int, float)):
            raise TypeError("成绩必须是数字")
        if value < 0 or value > 100:
            raise ValueError("成绩必须在0到100之间")
        self._score = value

stu = Student(85)
print(stu.score)  # 输出:85
stu.score = 92.5
print(stu.score)  # 输出:92.5
# stu.score = 101  # 抛出ValueError: 成绩必须在0到100之间

场景2:计算属性

有些属性不需要单独存储,而是通过其他属性计算得到的,也可以用@property来实现,比如矩形的面积和周长,不需要单独存,通过长和宽计算即可。

class Rectangle:
    def __init__(self, length, width):
        self.length = length
        self.width = width

    @property
    def area(self):
        # 面积属性,由长和宽计算得到,不需要单独存储
        return self.length * self.width

    @property
    def perimeter(self):
        # 周长属性,由长和宽计算得到
        return 2 * (self.length + self.width)

rect = Rectangle(5, 3)
print(rect.area)  # 输出:15
print(rect.perimeter)  # 输出:16
# 修改长和宽后,面积和周长会自动更新
rect.length = 10
print(rect.area)  # 输出:30

注意事项

  • 使用@property装饰的方法名不要和内部存储的属性名完全一致,通常内部属性用下划线开头,比如内部存为_age,装饰的方法名为age,避免递归调用导致栈溢出。
  • 如果只定义了@property的getter方法,没有定义setter方法,那么该属性就是只读的,外部尝试修改会抛出AttributeError。
  • @property装饰器是Python的语法糖,本质是将方法转换为描述符对象,理解描述符的原理可以更深刻地掌握它的工作机制,不过日常使用只需要掌握上述用法即可。

通过合理使用@property装饰器,我们可以让类的属性访问更加直观,同时有效保护属性的合法性,是Python面向对象编程中非常重要的一个工具。

Pythonproperty装饰器属性保护面向对象编程getter_setter修改时间:2026-06-26 15:48:24

免责声明:​ 已尽一切努力确保本网站所含信息的准确性。网站内容多为原创整理与精心编撰,观点力求客观中立。本站旨在免费分享,内容仅供个人学习、研究或参考使用。若引用了第三方作品,版权归原作者所有。如内容涉及您的权益,请联系我们处理。
内容垂直聚焦
专注技术核心技术栏目,确保每篇文章深度聚焦于实用技能。从代码技巧到架构设计,为用户提供无干扰的纯技术知识沉淀,精准满足专业提升需求。
知识结构清晰
覆盖从开发到部署的全链路。AI、前端、编程、数据库、服务器、建站、系统层层递进,构建清晰学习路径,帮助用户系统化掌握开发与运维所需的核心技术。
深度技术解析
拒绝泛泛而谈,深入技术细节与实践难点。无论是数据库优化还是服务器配置,均结合真实场景与代码示例进行剖析,致力于提供可直接应用于工作的解决方案。
专业领域覆盖
精准对应开发生命周期。从前端界面到后端编程,从数据库操作到服务器运维,形成完整闭环,一站式满足全栈工程师和运维人员的技术需求。
即学即用高效
内容强调实操性,步骤清晰、代码完整。用户可根据教程直接复现和应用于自身项目,显著缩短从学习到实践的距离,快速解决开发中的具体问题。
持续更新保障
专注既定技术方向进行长期、稳定的内容输出。确保各栏目技术文章持续更新迭代,紧跟主流技术发展趋势,为用户提供经久不衰的学习价值。