一、应用
1、@property一般应用在Python方法上,可以有效地将属性访问(attribute access)变成方法调用(method call)
2、简单的列子:如果单纯的学生的分数作为属性,那么将没有办法对分数进行检查(毕竟分数不能为负数和无限大)。
那么我们可以用@property将属性访问(attribute access)变成方法调用(method call)
1 class Student(object): 2 @property # 将属性的访问变成方法的调用(调用方式还是 "对象.方法名")
3 def score(self):
4 return self._score
6 # 通过socre.setter装饰的score即可对value进行修改,也可以进行参数检查 7 @score.setter 8 def score(self, value): 9 if not isinstance(value, int): 10 raise ValueError('score must be an integer!') 11 if value < 0 or value > 100: 12 raise ValueError('score must between 0 ~ 100!') 13 self._score = value 14 15 16 stu = Student() 17 stu.score = 78 18 print(stu.score)
二、实例:
创建一个代表金钱的类:
1 class Money: 2 def __init__(self, dollars, cents): 3 self.dollars = dollars 4 self.cents = cents
这个类后来被打包到一个Python库里,并且慢慢地被许多不同的应用使用。举个例子,另一个团队中的Python程序员Bob是这样使用Money类的:
1 money = Money(27, 12) 2 message = "I have {:d} dollars and {:d} cents." 3 print(message.format(money.dollars, money.cents)) 4 # "I have 27 dollars and 12 cents." 5 money.dollars += 2 6 money.cents += 20 7 print(message.format(money.dollars, money.cents)) 8 # "I have 29 dollars and 32 cents."
但是,因为某种业务需求不再记录美元和美分,而是仅仅记录美分,这样的导致代码需要重构;许多团队都复用了她的代码。因此,她需要协调他们的代码库与自己的修改保持一致。
这时候使用Python内建的property装饰器,会使问题简单许多。代码如 下:
1 class Money: 2 def __init__(self, dollars, cents): 3 # 改成美分 4 self.total_cents = dollars * 100 + cents 5 6 # @property修饰的函数可以通过"obj.方法名" 直接调用;但是不能直接修改 7 # 如 money.dollars = 100 ,这样是会报错的。 8 # 但是我可以为该方法定一个setter方法来修改其值;第13行的就定义了这样一个方法。 9 @property 10 def dollars(self): 11 # 将@dollars.setter转化的美分除以100 返回给以前的团队使用。 12 return self.total_cents // 100; 13 14 # 该方法与@property修饰的方法名称一样 15 @dollars.setter 16 def dollars(self, new_dollars): 17 # 将传进的美元转化成美分,方便其他业务的使用 18 self.total_cents = 100 * new_dollars + self.cents 19 20 21 @property 22 def cents(self): 23 return self.total_cents % 100; 24 25 @cents.setter 26 def cents(self, new_cents): 27 self.total_cents = 100 * self.dollars + new_cents 28 29 30 # 他的代码完全没有变动,但是却可以正常调用Money类。 31 money = Money(27, 12) 32 message = "I have {:d} dollars and {:d} cents." 33 print(message.format(money.dollars, money.cents)) 34 # "I have 27 dollars and 12 cents." 35 money.dollars += 2 36 money.cents += 20 37 print(message.format(money.dollars, money.cents)) 38 # "I have 29 dollars and 32 cents."# 代码逻辑也没有问题。 39 money.cents += 112 40 print(message.format(money.dollars, money.cents)) 41 # "I have 30 dollars and 44 cents."