关于@property装饰器
在Python中我们使用@property装饰器来把对函数的调用伪装成对属性的访问。
那么为什么要这样做呢?因为@property让我们将自定义的代码同变量的访问/设定联系在了一起,同时为你的类保持一个简单的访问属性的接口。
举个栗子,假如我们有一个需要表示电影的类:
1 2 3 4 5 6 7 8 |
class Movie(object): def __init__(self, title, description, score, ticket): self.title = title self.description = description self.score = scroe self.ticket = ticket |
你开始在项目的其他地方使用这个类,但是之后你意识到:如果不小心给电影打了负分怎么办?你觉得这是错误的行为,希望Movie类可以阻止这个错误。 你首先想到的办法是将Movie类修改为这样:
1 2 3 4 5 6 7 8 |
class Movie(object): def __init__(self, title, description, score, ticket): self.title = title self.description = description self.ticket = ticket if score < 0: raise ValueError("Negative value not allowed:{}".format(score)) self.score = scroe |
但这行不通。因为其他部分的代码都是直接通过Movie.score来赋值的。这个新修改的类只会在__init__方法中捕获错误的数据,但对于已经存在的类实例就无能为力了。如果有人试着运行m.scrore= -100,那么谁也没法阻止。那该怎么办?
Python的property解决了这个问题。
我们可以这样做
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
class Movie(object): def __init__(self, title, description, score): self.title = title self.description = description self.score = score self.ticket = ticket @property def score(self): return self.__score @score.setter def score(self, score): if score < 0: raise ValueError("Negative value not allowed:{}".format(score)) self.__score = score @score.deleter def score(self): raise AttributeError("Can not delete score") |
这样在任何地方修改score都会检测它是否小于0。
property的不足
对property来说,最大的缺点就是它们不能重复使用。举个例子,假设你想为ticket字段也添加非负检查。下面是修改过的新类:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 |
class Movie(object): def __init__(self, title, description, score, ticket): self.title = title self.description = description self.score = score self.ticket = ticket yon-e">score self.ticket = ticket Ե影的类:
你开始在项目的其他地方使用这个类,但是之后你意识到:如果不小心给电影打了负分怎么办?你觉得这是错误的行为,希望Movie类可以阻止这个错误。 你首先想到的办法是将Movie类修改为这样:
但这行不通。因为其他部分的代码都是直接通过Movie.score来赋值的。这个新修改的类只会在__init__方法中捕获错误的数据,但对于已经存在的类实例就无能为力了。如果有人试着运行m.scrore= -100,那么谁也没法阻止。那该怎么办? Python的property解决了这个问题。 我们可以这样做
这样在任何地方修改score都会检测它是否小于0。 property的不足 对property来说,最大的缺点就是它们不能重复使用。举个例子,假设你想为ticket字段也添加非负检查。下面是修改过的新类:
|