我在2016年的时候,写过一篇文章,介绍@property装饰器。4年过去了,本来以为这个装饰器使用起来应该是很自然的事情,但还是有同学不知道在什么场景下可以使用它。
创新互联是专业的临川网站建设公司,临川接单;提供做网站、网站建设,网页设计,网站设计,建网站,PHP网站建设等专业做网站服务;采用PHP框架,可快速的进行临川网站开发网页制作和功能扩展;专业做搜索引擎喜爱的网站,专业的做网站团队,希望更多企业前来合作!
他们是这样说的:
- class People:
- def __init__(self, name):
- self.name = name
- self._work = '还没有找到工作'
- @property
- def work(self):
- return self._work
- @work.setter
- def work(self, value):
- self._work = value
运行效果如下图所示:
但实际上,这段代码里面,@property装饰器根本没有任何存在的必要,代码完全可以进一步简化:
- class People:
- def __init__(self, name):
- self.name = name
- self.work = '还没有找到工作'
运行结果完全一样:
那么,使用@property装饰器的意义在哪里呢?
的确,在上面的例子里,@property装饰器没有任何存在的必要,因为这里读取一个对象的属性,仅仅是“返回数据”而已。但有些情况下,不仅仅要读取,还要计算。
我举一个例子,不知道你有没有这样的经历,你刚刚看了一眼手机,发现现在时间是23:10分。30秒以后,你朋友碰巧问你多少点了,你立刻回答:23:10分。他一看手表,还真是。于是惊呼,你怎么不看表就知道时间?
例如我们现在要实现一个ProxyProvider类,它读取 Redis,获取最新的代理 IP,然后随机返回一条。另外有一个程序,会增加新的代理 IP 到 Redis 中。但频率不高。
所以,ProxyProvider这个类,不需要每次获取 IP 的时候都读取数据库,每小时读取一次就可以了。如果不用@property装饰器,你可能会这样写代码:
- import time
- import random
- class ProxyProvider:
- def __init__(self):
- self.pool = []
- self.last_update_time = 0
- def get_proxy(self):
- now = time.time()
- if now - self.last_update_time > 3600 or not self.pool:
- selfself.pool = self.get_all_proxies_from_redis()
- return random.choice(self.pool)
如果你经常看 Java 代码,你会发现大量的这种get_xxx、set_xxx的写法。
于是,调用的时候,要这样调用:
- provider = ProxyProvider()
- provider.get_proxy()
如果用@property,那么代码可以改写为:
- import time
- import random
- class ProxyProvider:
- def __init__(self):
- self.pool = []
- self.last_update_time = 0
- @property
- def proxy(self):
- now = time.time()
- if now - self.last_update_time > 3600 or not self.pool:
- selfself.pool = self.get_all_proxies_from_redis()
- return random.choice(self.pool)
于是读取的时候,这样写:
- provider = ProxyProvider()
- provider.proxy # 注意这里不加括号
我们可以看到,整体代码逻辑是一样的,代码里并没有精简。不过在调用的时候,前者是调用一个方法,后者是读取一个属性。
同理,如果要修改数据,不使用@property的时候,需要实现一个set_xxx方法。但是使用了@property装饰一个方法,也可以在设置数据的时候实现一些内部逻辑,例如:
- import time
- import random
- class ProxyProvider:
- def __init__(self):
- self.pool = []
- self.special_ip = set()
- self.last_update_time = 0
- @property
- def proxy(self):
- now = time.time()
- if now - self.last_update_time > 3600 or not self.pool:
- selfself.pool = self.get_all_proxies_from_redis()
- return random.choice(self.pool + list(self.special))
- @proxy.setter
- def proxy(self, value):
- if not value.startswith('http'):
- proxy = f'http://{ip}'
- if proxy in self.special_ip:
- return
- self.special_ip.add(proxy)
而对于调用者来说,这些复杂的检查逻辑都是透明的:
- provider = ProxyProvider()
- provider.proxy = '123.45.67.89'
对于习惯于 Java 的人来说,他们可能喜欢显式写出get_xxx和set_xxx方法。但是对于习惯 Python 的人来说,我觉得使用@property会让代码的可读性更好。
文章名称:在什么情况下使用@property比较好?
当前路径:http://www.gawzjz.com/qtweb/news11/191061.html
网站建设、网络推广公司-创新互联,是专注品牌与效果的网站制作,网络营销seo公司;服务项目有等
声明:本网站发布的内容(图片、视频和文字)以用户投稿、用户转载内容为主,如果涉及侵权请尽快告知,我们将会在第一时间删除。文章观点不代表本网站立场,如需处理请联系客服。电话:028-86922220;邮箱:631063699@qq.com。内容未经允许不得转载,或转载时需注明来源: 创新互联