Python深入分析@property装饰器的应用
本文深入解析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装饰器的内容,请搜索本站历史文章或继续浏览后续相关文章,感谢大家的支持!
本站声明
本文内容仅供参考,不代表本站观点。转载或引用请注明出处。如发现内容问题,请通过联系我们页面反馈。













