Python深入分析@property装饰器的应用

咖啡半糖
咖啡半糖
发布时间:2026-10-15 | 5人浏览过
原创

本文深入解析Python中@property装饰器的核心应用。详细阐述如何通过@property将方法转化为属性调用,简化数据访问流程并防止外部直接赋值。文章对比了装饰器方式与类属性方式两种定义手段,重点讲解利用@property进行参数校验与异常抛出的最佳实践,帮助开发者构建更安全、简洁的类接口。

什么是@property

简单来说,当类中的某个方法被@property装饰器处理后,调用者可以像访问普通属性那样直接调用该方法。这种方式不仅简化了数据获取的流程,还能有效避免将内部属性直接暴露给外部,从而防止使用者进行不合理的赋值操作。在使用时,需要特别注意以下两点:

  • 调用被@property装饰的方法时,不需要添加括号。
  • 该方法的定义中,必须且只能包含self这一个参数。
>>> class Goods():
        def __init__(self,unit_price,weight):
            self.unit_price = unit_price
            self.weight = weight
        @property
        def price(self):
            return self.unit_price * self.weight
>>> lemons = Goods(7,4)
>>>
>>> lemons.price
28

通过上述方式调用属性,实际上是在内部执行了price方法,@property将复杂的处理逻辑封装在方法内部,用户只需调用对应的属性名即可获取结果。

定义@property属性的两种常见方式

A、使用装饰器方式

即在类的方法上方直接应用@property装饰器,这是前文所述的主要方式。

B、使用类属性方式

通过创建一个实例对象并将其赋值给类属性的方式来定义。

>>> class Lemons():
        def __init__(self,unit_price=7):
            self.unit_price = unit_price
        def get_unit_price(self):
            return self.unit_price
        def set_unit_price(self,new_unit_price):
            self.unit_price = new_unit_price
        def del_unit_price(self):
            del self.unit_price
        x = property(get_unit_price, set_unit_price, del_unit_price)
>>> fruit = Lemons()
>>> 
>>> fruit.x                         #调用 fruit.x 触发 get_unit_price
7
>>> 
>>> fruit.x = 9                     #调用 fruit.x = 9 触发 set_unit_price
>>> 
>>> fruit.x
9
>>> 
>>> fruit.unit_price                #调用 fruit.unit_price 触发 get_unit_price
9
>>> del fruit.x                     #调用 del fruit.x 触发 del_unit_price 
>>> 
>>> fruit.unit_price
Traceback (most recent call last):
  File "<pyshell#23>", line 1, in <module>
    l.unit_price
AttributeError: 'Lemons' object has no attribute 'unit_price'

property()方法可以接收四个参数,具体如下:

  • 第一个参数是获取属性值的方法名,当执行 对象.属性 时会自动触发此方法。
  • 第二个参数是设置属性值的方法名,当对属性进行赋值时会自动触发此方法。
  • 第三个参数是删除属性值的方法名,当删除属性时会自动触发此方法。
  • 第四个参数是字符串类型的文档描述,当调用 对象.属性.__doc__ 时会返回此描述信息。

@property属性值的限制与校验

如果在绑定属性时直接暴露属性,虽然编写简单,但无法检查参数合法性,导致属性值可以被随意修改,存在安全隐患。

class Person(object):
    pass
p = Person()
p.age = 1000

如上例所示,类中的属性若被随意修改,显然不符合设计初衷。为了限制age的取值范围,可以通过一个 set_age() 方法来设置值,再通过一个 个 get_age() 方法来获取值。在 set_score() 方法内部,就可以对传入的参数进行检查。

# -*- coding: utf-8 -*-
class Person(object):
    # score属性的值 限制范围为:0-88
    def get_age(self):
        return self.__age
    def set_age(self, value):
        if 0 <= value <= 88:
            self.__age = value
        else:
            self.__age = 0  # 给age一个初始值0
            raise ValueError('age的值必须在0-88之间')  # 自动抛异常
if __name__ == '__main__':
    p = Person()
    p.set_age(100)
    p.get_age()

ValueError('age的值必须在0-88之间')

当我们设置限定age的范围时,如果尝试超出范围的值,set_age 方法会自动抛出异常。然而,上述手动实现的方式较为繁琐,因此引入了装饰器概念,装饰器可以为函数动态添加功能。对于类方法,装饰器同样有效。Python内置的 @propert 装饰器正是负责将一个普通方法转换为属性调用的工具。

# -*- coding: utf-8 -*-
class Person(object):
    # score属性的值 限制范围为:0-88
    @property  # 把 age 属性暴露出去
    def age(self):
        return self.__age
    @age.setter  # 当前 age 属性可以允许赋值
    def age(self, value):
        if 0 <= value <= 88:
            self.__age = value
        else:
            self.__age = 0  # 给age一个初始值0
            raise ValueError('age的值必须在0-88之间')  # 自动抛异常
    @property
    def name(self):
        self.__name = '张三'
        return self.__name
if __name__ == '__main__':
    p = Person()
    p.age = 18
    print(p.age)  # age属性可以读,可以写
    print(p.name)  # name 只读属性

@property 的具体实现逻辑较为复杂,建议先关注其使用场景。

只需将一个getter方法加上 @property 装饰器,即可将其变为属性。此时,@property 内部会创建另一个装饰器 @age.setter,负责将setter方法转换为属性赋值操作。这样,我们就拥有了一个既可读又可写且可控的属性操作接口。

至此,关于Python中@property装饰器应用的深入分析介绍完毕。如需了解更多相关Python @property装饰器的内容,请搜索本站历史文章或继续浏览后续相关文章,感谢大家的支持!

相关标签:

本站声明

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

Python 相关产品和应用

全部下载

专题列表