今天,谈谈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?
  1. class T(object):
  2. age = 21
  3. t = T()
  4. t.name = "ilovebaiyang"
  5. print "dir(T):", dir(T)
  6. print "dir(t):", dir(t)

这个打印的结果是:

view plaincopy to clipboardprint?
  1. dir(T): ['__class__', '__delattr__', '__dict__', '__doc__', '__format__', '__getattribute__', '__hash__', '__init__', '__module__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '__weakref__', 'age']
  2. 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?
  1. T.__dict__:  {'__dict__': , '__module__': '__main__', '__weakref__': , 'age': 21, '__doc__': None}
  2. t.__dict__:  {'name': 'ilovebaiyang'}

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

  • 1.先查找该实例的__dict__,如果有,返回,否则进行第二步
  • 2.查找类的__dict__,如果有返回,没有的话,继续查找该类的父类,直到基类,如果还没有,抛出异常。

当然,其实python中的查找还做了很多其他事,特别是一些隐含的调用,如果我们重写这些隐含的调用,就可以写出符合我们的数据。
看下面的例子:

view plaincopy to clipboardprint?
  1. class T(object):
  2. def __setattr__(self, name, value):
  3. print "__setattr__ called "
  4. object.__setattr__(self, name, value)
  5. def __getattr__(self, name):
  6. print "__getattr__ called "
  7. def __getattribute__(self, name):
  8. print "__getattribute__ called"
  9. return object.__getattribute__(self, name)
  10. t = T()
  11. t.name = "baiyang"
  12. print "t", t.name
  13. t.baiyang

结果:

  1. __setattr__ called
  2. t __getattribute__ called
  3. baiyang
  4. __getattribute__ called
  5. __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?
  1. class T(object):
  2. age = 21
  3. def __setattr__(self, name, value):
  4. print "__setattr__ called "
  5. object.__setattr__(self, name, value)
  6. def __getattr__(self, name):
  7. print "__getattr__ called "
  8. def __getattribute__(self, name):
  9. print "__getattribute__ called"
  10. return object.__getattribute__(self, name)
  11. t = T()
  12. t.__dict__["name"] = "baiyang"
  13. print "t.__dict__: ", t.__dict__["name"]
  14. print "t.age: ", t.age
  15. print "t.__dict__['age']: ", t.__dict__["age"]

结果

view plaincopy to clipboardprint?
  1. __getattribute__ called
  2. t.__dict__:  __getattribute__ called
  3. baiyang
  4. t.age:  __getattribute__ called
  5. 21
  6. t.__dict__['age']:  __getattribute__ called
  7. Traceback (most recent call last):
  8. File "C:\Users\Administrator\Desktop\lab\SogouW\Freq\test.py", line 18, in
  9. print "t.__dict__['age']: ", t.__dict__["age"]
  10. 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/

转载于:https://www.cnblogs.com/ibaiyang/archive/2012/12/07/2807345.html

#PYTHON#数据模型相关推荐

  1. python数据模型的意义_Python 数据模型

    Guido 对语言设计美学的深入理解让人震惊.我认识不少很不错的编程语言设计者,他们设计出来的东西确实很精彩,但是从来都不会有用户.Guido 知道如何在理论上做出一定的妥协,设计出来的语言让使用者觉 ...

  2. gj3 Python数据模型(魔法函数)

    3.1 什么是魔法函数 类里面,实现某些特性的内置函数,类似 def __xx__(): 的形式. 不要自己定义XX,并不是和某个类挂钩的 class Company(object):def __in ...

  3. python 数据模型

    点击上方"算法猿的成长",关注公众号,选择加"星标"或"置顶" 总第 129 篇文章,本文大约  4500 字,阅读大约需要 15 分钟 最 ...

  4. 【Python】理解Python(1) - Python数据模型,is关键字,类型

    文章目录 Python的数据模型 对象的标识 对象的类型 对象的值 is 关键字 判断一个变量是否指向函数 types模块中定义的类型 本文是作者对Python官方文档的理解和试验结果,不保证技术准确 ...

  5. python的数据模型_python高级(一)—— python数据模型(特殊方法)

    本文主要内容 collections.namedtuple __getitem__ 和 __len__ __repr__和__str__ __abs__.__add__和__mul__ __bool_ ...

  6. python数据模型_#PYTHON#数据模型 | 学步园

    今天,谈谈python中的数据模型,当然你可以不了解这些东西,照样可以写出漂亮的python代码,但是"知其然知其所以然"是我的作风,总是不明白python的一些机制,心里很不爽. ...

  7. 流畅的python读书笔记-第一章Python 数据模型

    第一章 python数据类型 1 隐式方法 利用collections.namedtuple 快速生成类 import collectionsCard = collections.namedtuple ...

  8. python数据模型搭建_python之路(19)django数据库模型(model)

    前言 object relation mapping(ORM)关系对象映射表,一个类实例映射为一条表记录 目录 数据库配置 1.django 默认使用sqlite的数据库,如果需要使用mysql数据库 ...

  9. 流畅的Python 1. Python数据模型(特殊方法 __func__())

    文章目录 1. `__getitem__().__len__()` 方法 2. 特殊方法 1. __getitem__().__len__() 方法 举一个扑克牌的例子 import collecti ...

  10. 流畅的python 数据模型

    一摞python风格的纸牌 import collections from random import choice card = collections.namedtuple("card& ...

最新文章

  1. 关于Input内容改变的触发事件
  2. Leet Code OJ 简单(二)
  3. Serverless Kubernetes 应用部署及扩缩容
  4. php 生成pdf 中文,php采用tcpdf生成pdf支持中文,图片
  5. 数据权限设计(原创)
  6. iOS 数据持久化-- FMDB
  7. asp.net + ajax + sqlserver 自动补全功能,asp.net+ajax+sqlserver自动补全功能实现解析
  8. pcb板子制作各层的解释和用法
  9. html alert 确认加事件,js事件中有alert执行顺序的问题
  10. zookeeper源码_阿里P8带你从源码级别——深挖Zookeeper监听机制
  11. mysql学习书籍推荐
  12. 【Matlab】函数uigetfile的使用
  13. GetLastError的使用和返回值定义大全
  14. 2段代码实现在所有浏览器下显示特殊字体(附字体转换工具)
  15. 【C语言】if、if else、else、switch的用法
  16. 一张纸厚度是多少毫米_一张A4纸的厚度是多少mm?
  17. 关于linux下UART串口编程的困惑
  18. 8 Babylonjs基础入门 相机,模型碰撞和重力效果
  19. C. Candy Store(数学)
  20. 根据判断PC浏览器类型和手机屏幕像素自动调用不同CSS

热门文章

  1. c primer plus中文版_如何成为一名厉害的C/C++程序员?
  2. 数据结构实验题:用栈求解n皇后问题
  3. java log4j 多线程_针对log4j 1.2.15中的并发锁问题,到底是io瓶颈,还是锁竞争导致线程block?...
  4. 容器技术Docker K8s 40 Serverless Kubernetes(ASK)详解-阿里云弹性容器实例ECI产品概述
  5. 价值连城 生成对抗网络(Gans) 的作者Ian Goodfellow的采访 给深度学习从业者的建议
  6. SageMaker 基于 Blazing Text的中文新闻标题分类
  7. Layout anchors徒手写AutoLayout Swift
  8. Docker MySQL 8 慢查询日志监控详解
  9. 算法:Reverse Words in a String(翻转字符串里的单词)
  10. ELMo ,LM:一串词序列的概率分布probability distribution over sequences of words