设为首页 收藏本站
查看: 663|回复: 0

[经验分享] 用 Python 的 Descriptor 特性解决一个变态的问题

[复制链接]

尚未签到

发表于 2017-5-5 09:44:12 | 显示全部楼层 |阅读模式
  Python 中的 Decorator 大家见得多了,但 Descriptor 用过的估计还少,它主要是 Python 自身来实现库的一些特性,比如 staticmethod 之类的,今天有机会学习、试验了 Descriptor,小有所得,跟大家分享。
  今天 Jeff 给我们出了一道难题:有个叫 data 的某个 class 的实例,它有一个 item 属性,它可能是一个对象(姑且假设它是个 str object),也可能是一序列对象(比如 list object),在这个前题下,希望做到以下代码能够工作:
  # 当 data.item 是一个序列data.item = ['lai', 'yong', 'hao']print(data.item) # output: ['lai', 'yong', 'hao']for i in data.item:print i# output:laiyonghao# 当 data.item 是单个元素data.item = 'lai'print(data.item) # output: laifor i in data.item:print i# output: lai
  如果你现在觉得没啥,那肯定是没看仔细。我来提醒一下你,最后一行的 output 居然不是 lai 三个字母分成三行!
  也就是说 data.item 要做到当它是单个元素的时候,普通场合要跟单元元素一样,而迭代的场合,要跟包含多个元素的序列一样!这个要求太变态了。这么有挑战的问题,我马上祭出 python documentation,天不负苦心人,我找到了 Descriptor 这个我以前从未使用过的特性,最后解决了这个问题。详情多讲无益,直接上代码:
  #!/usr/bin/env python# -*- coding:utf-8 -*-from __future__ import print_functionclass ItemDescriptor(object):def __init__(self):self._data = []def __get__(self, instance, type = None):if len(self._data) == 1:tmp = self._data[0]class Wrapper(tmp.__class__): # 注意它的父类def __iter__(obj):# 这里使用的是 obj 不是 self,因为 self 已经被用了return self._data.__iter__()def next(obj):return self._data.next()return Wrapper(tmp)return self._datadef __set__(self, obj, val):if isinstance(val, list):self._data = valreturnself._data = [val]class Foo(object):item = ItemDescriptor() # 重要!foo = Foo()# 输出 Jeff,而不是 Jeff 一个字母一行foo.item = 'Jeff' print(foo.item)# 它的行为跟 'Jeff' 一样print('f' in foo.item)# 但迭代的时候,像 ['jeff'] 一样for i in foo.item:print(i)# 输出四行单词,而不是一行 :)foo.item = ['lai', 'pan', 'jeff', 'ken']print(foo.item)# 它的行为像 ['lai', 'pan', 'jeff', 'ken'] 一样print('ken' in foo.item)# 迭代时行为也像 ['lai', 'pan', 'jeff', 'ken'] 一样for i in foo.item:print(i)print('#' * 30)
  输出:
  lai@sd:~$ python test_descriptor.py JeffTrueJeff['lai', 'pan', 'jeff', 'ken']Truelaipanjeffken##############################
  最后,多说一句这些代码在 py2.6 和 py3.1 下测试通过,兼容两大版本。

运维网声明 1、欢迎大家加入本站运维交流群:群②:261659950 群⑤:202807635 群⑦870801961 群⑧679858003
2、本站所有主题由该帖子作者发表,该帖子作者与运维网享有帖子相关版权
3、所有作品的著作权均归原作者享有,请您和我们一样尊重他人的著作权等合法权益。如果您对作品感到满意,请购买正版
4、禁止制作、复制、发布和传播具有反动、淫秽、色情、暴力、凶杀等内容的信息,一经发现立即删除。若您因此触犯法律,一切后果自负,我们对此不承担任何责任
5、所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其内容的准确性、可靠性、正当性、安全性、合法性等负责,亦不承担任何法律责任
6、所有作品仅供您个人学习、研究或欣赏,不得用于商业或者其他用途,否则,一切后果均由您自己承担,我们对此不承担任何法律责任
7、如涉及侵犯版权等问题,请您及时通知我们,我们将立即采取措施予以解决
8、联系人Email:admin@iyunv.com 网址:www.yunweiku.com

所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其承担任何法律责任,如涉及侵犯版权等问题,请您及时通知我们,我们将立即处理,联系人Email:kefu@iyunv.com,QQ:1061981298 本贴地址:https://www.yunweiku.com/thread-373282-1-1.html 上篇帖子: UltraJSON——Python 的极速 JSON 编解码器 下篇帖子: Python使用Com组件及Access查询分析类实现
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

扫码加入运维网微信交流群X

扫码加入运维网微信交流群

扫描二维码加入运维网微信交流群,最新一手资源尽在官方微信交流群!快快加入我们吧...

扫描微信二维码查看详情

客服E-mail:kefu@iyunv.com 客服QQ:1061981298


QQ群⑦:运维网交流群⑦ QQ群⑧:运维网交流群⑧ k8s群:运维网kubernetes交流群


提醒:禁止发布任何违反国家法律、法规的言论与图片等内容;本站内容均来自个人观点与网络等信息,非本站认同之观点.


本站大部分资源是网友从网上搜集分享而来,其版权均归原作者及其网站所有,我们尊重他人的合法权益,如有内容侵犯您的合法权益,请及时与我们联系进行核实删除!



合作伙伴: 青云cloud

快速回复 返回顶部 返回列表