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

[经验分享] 你懂PYTHON吗【谈PYTHON中的数据模型】值得一看

[复制链接]

尚未签到

发表于 2017-5-2 06:08:32 | 显示全部楼层 |阅读模式
  今天,谈谈python中的数据模型,当然你可以不了解这些东西,照样可以写出漂亮的python代码,但是“知其然知其所以然”是我的作风,总是不明白python的一些机制,心里很不爽。结合python的doc和一篇文章,差不多明白了python的哲理。
  我觉得有必要将python中的文档的一些重要语句拿出来。
  Objects are Python’s abstraction for data. All data in a Python program is represented by objects or by relations between objects.
Every object has an identity, a type and a value.

  为什么我这里要强调这里的对象,有对象以为着有一些属性(函数也罢,变量也罢都是属性)与之关联,你操作一个对象,其实就是在和这些属性打交道。
  在这里,我集中在python中的类,去弄明白python中的类究竟是怎么完成其功能的.
A class has a namespace implemented by a dictionary object. Class attribute references are translated to lookups in this dictionary.
  这句话很重要,一个类有其自己的namespace(命名空间),而且这个命名空间的实现本质上是一个字典。换句话说,你对一个类的操作其实就是在对这个“特殊”的字典进行操作,那么怎么去区分类的实例和类呢,其实在python中,类的实例也有一个字典,去记录该实例的属性。
view plaincopy to clipboardprint?


  • class T(object):  
  •     age = 21  
  •   
  • t = T()  
  • t.name = "ilovebaiyang"  
  •   
  • print "dir(T):", dir(T)  
  • print "dir(t):", dir(t)  

  这个打印的结果是:
view plaincopy to clipboardprint?


  • dir(T): ['__class__''__delattr__''__dict__''__doc__''__format__''__getattribute__''__hash__''__init__''__module__''__new__''__reduce__''__reduce_ex__''__repr__''__setattr__''__sizeof__''__str__''__subclasshook__''__weakref__''age']  
  •   
  • dir(t): ['__class__''__delattr__''__dict__''__doc__''__format__''__getattribute__''__hash__''__init__''__module__''__new__''__reduce__''__reduce_ex__''__repr__''__setattr__''__sizeof__''__str__''__subclasshook__''__weakref__''age''name']  

  其中有些属性是从object上继承来的,比如__doc__, __setattr__,__dict__等等,其中值得注意的是自定义属性,age和name,他们分别存在于类T中和类T的实例t中,那么为什么在dir(t)中出现了age的属性呢,原因是从它的类上复制过来的,而且如果我们打印他们的id,其实他们的id是一样的。在这里,我们出现了一个疑问,前面提到的命名空间的字典就是dir()函数产生的字典么,看上去貌似是,因为它的确记录了该对象的所有属性,其实这个是错误的,原因我们就要回到dir函数上了,它的作用是罗列出当前对象的所有属性,包括父类的。其实,前面提到的命名空间是的__dict__成员,所有与该对象对应的属性全部放在这个字典里。
  我们打印出来看看
view plaincopy to clipboardprint?


  • T.__dict__:  {'__dict__': , '__module__''__main__''__weakref__': , 'age': 21, '__doc__': None}  
  •   
  • t.__dict__:  {'name''ilovebaiyang'}  

  这一下才会和我们想象的一样,name属性只存在实例中。
接下来是属性的查找:
如果我们要打印t.age,怎么搜索

  • 1.先查找该实例的__dict__,如果有,返回,否则进行第二步
  • 2.查找类的__dict__,如果有返回,没有的话,继续查找该类的父类,直到基类,如果还没有,抛出异常。
  当然,其实python中的查找还做了很多其他事,特别是一些隐含的调用,如果我们重写这些隐含的调用,就可以写出符合我们的数据。
看下面的例子:
view plaincopy to clipboardprint?


  • class T(object):  
  •     def __setattr__(self, name, value):  
  •         print "__setattr__ called "  
  •         object.__setattr__(self, name, value)  
  •   
  •     def __getattr__(self, name):  
  •         print "__getattr__ called "   
  •   
  •     def __getattribute__(self, name):  
  •         print "__getattribute__ called"  
  •         return object.__getattribute__(self, name)  
  •   
  • t = T()  
  • t.name = "baiyang"  
  • print "t", t.name  
  • t.baiyang  

  结果:

  • __setattr__ called  
  • t __getattribute__ called  
  • baiyang  
  • __getattribute__ called  
  • __getattr__ called  

  分析以上的结果,当t.name被执行时,先调用了__setattr__函数;当print “t”, t.name时,调用了__getattribute__函数;当t.baiyang时,调用了__getattr__函数,因为t没有baiyang这个属性,故调用这个函数。
  其实简单的想一下,会明白,我们在操作namespace这个字典时,我们都会隐式的调用相应的函数,这些函数可以用来进行数据的验证。
总结一下,在操作类的实例的属性时,我们需要关注一下函数:
object.__setattr__(self, name, value)
object.__getattr__(self, name)
object.__delattr__(self, name)
object.__getattribute__(self, name)
  其中你对任何对象的属性访问时,都会隐式的调用__getattribute__方法,比如你调用t.__dict__,其实你执行了t.__getattribute__(“__dict__”)函数。
  神奇的python,把字典用的如此灵活,由此可以看出字典在python的地位是何其的重要。
  在这里,我们或许想到了怎么不去隐式的调用这些函数,对,我们可以直接去操作类或者类实例的__dict__。看看下面的例子:
view plaincopy to clipboardprint?


  • class T(object):  
  •     age = 21  
  •     def __setattr__(self, name, value):  
  •         print "__setattr__ called "  
  •         object.__setattr__(self, name, value)  
  •   
  •     def __getattr__(self, name):  
  •         print "__getattr__ called "   
  •   
  •     def __getattribute__(self, name):  
  •         print "__getattribute__ called"  
  •         return object.__getattribute__(self, name)  
  •   
  • t = T()  
  • t.__dict__["name"] = "baiyang"  
  • print "t.__dict__: ", t.__dict__["name"]  
  • print "t.age: ", t.age  
  • print "t.__dict__['age']: ", t.__dict__["age"]  

  结果
view plaincopy to clipboardprint?


  • __getattribute__ called  
  • t.__dict__:  __getattribute__ called  
  • baiyang  
  • t.age:  __getattribute__ called  
  • 21  
  • t.__dict__['age']:  __getattribute__ called  
  •   
  • Traceback (most recent call last):  
  •   File "C:\Users\Administrator\Desktop\lab\SogouW\Freq\test.py", line 18, in  
  •     print "t.__dict__['age']: ", t.__dict__["age"]  
  • KeyError: 'age'  

  我们来分析一下:
1.t__dict__["name"] = “baiyang”其中调用了__getattribute__函数,因为__dict__本身也是一个属性的,所以它必须会执行的;但是你会发现此时__setattr__并没有执行,达到了我们想要的效果;
2.print “t.age: “, t.age
print “t.__dict__['age']: “, t.__dict__["age"]这才是重点,第二条语句抛出了KeyError的异常,再一次证明了age只是存在于类的namespace中。
  最后,我们与python中的descriptor进行比较:
可以看这篇文章,我就不细讲了。
主要一点就是descriptor对应的函数是
object.__get__(self, instance, owner)
object.__set__(self, instance, value)
object.__delete__(self, instance)
可以看出少了attr这个词,也以为着我们必须将他们区分看。descriptor是对类的实例进行的操作,内建函数property()就是通过这个方式实现的。看了此文,是不是对python的工作机制更加了解了呢?
好了,在这里提几个问吧,你可以去网上搜到答案

  • 如何创建immutable的数据,我之前的一篇文章已经给出了答案。
  • 如何创建singleton模式的数据
  如果你明白了上面的文章,你就会明白,不论你想写出什么样的数据,只要去重写python中一些内在的函数即可。
  -----------------打造高质量的文章 更多关注 把酒泯恩仇---------------
  为了打造高质量的文章,请  推荐  一个吧。。。。谢谢了,我会写更多的好文章的。
  请关注sina微博:http://weibo.com/baiyang26
  把酒泯恩仇官方博客:http://www.ibaiyang.org 【推荐用google reader订阅】
  把酒泯恩仇官方豆瓣:http://www.douban.com/people/baiyang26/

运维网声明 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-371783-1-1.html 上篇帖子: 使用python进行编程.工具是次要的.关键在理解代码. 下篇帖子: 用Eclipse开发Python的详细配置
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

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

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

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

扫描微信二维码查看详情

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


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


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


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



合作伙伴: 青云cloud

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