首先不要脸的放上个人网站:www.comingnext.cn

1.关于数据模型

在Python的官方文档中是这样说的:

对象是Python对数据的抽象。Python程序中所有数据都由对象或对象之间的关系表示。在某种意义上,为了和冯诺依曼存储程序计算机模型保持一致,代码和数据一样也是一个对象(冯诺依曼模型中提到,数据和程序都以0,1存储于存储器中)

简单的说,Python中的一切数据要么是对象,要么和对象有关系

如果你带着来自其他面向对象语言的经验进入 Python 的世界,会对 len(object) 而不是 object.len() 写法觉得不适。但是它体现了Python的一种设计思想,也是pythonic的关键所在,而这种思想则体现在Python的数据模型中。

数据模型其实是对 Python 框架的描述,它规范了这门语言自身构建模块的接口,这些模块包括但不限于序列、迭代器、函数、类和上下文管理器。

2.特殊方法(魔术方法)

不管在哪种框架下写程序,都会花费大量时间去实现那些会被框架本身调用的方法, Python 也不例外。

Python 解释器碰到特殊的句法时,会使用特殊方法去激活一些基本的对象操作,这些特殊方法的名字以两个下划线开头,以两个下划线结尾(例如 __ getitem__ )。比如 obj[key] 的背后就是 __getitem__ 方法,为了能求得 my_collection[key] 的值,解释器实际上会调用 my_collection._getitem_(key)。 魔术方法(magic method)是特殊方法的昵称。特殊方法也叫双下方法(dunder method)。

通过实现特殊方法,自定义数据类型可以表现得跟内置类型一样,从而让我们写出更具表达力的代码——或者说,更具 Python 风格的代码。例如下面的一段代码:

 import collections

 Card = collections.namedtuple('Card', ['rank', 'suit'])

 class FrenchDeck:
ranks = [str(n) for n in range(2, 11)] + list('JQKA')
suits = 'spades diamonds clubs hearts'.split() def __init__(self):
self._cards = [Card(rank, suit) for suit in self.suits
for rank in self.ranks] def __len__(self):
return len(self._cards) def __getitem__(self, position):
return self._cards[position]

这段代码是一副扑克牌的原型,在这个自定义类中,有三个我们写的特殊方法,通过这几个方法,我们的自定义类就可以在使用的时候像Python的内置类型一样。 我们把这段代码保存为frenchdeck.py文件,然后通过命令行窗口进入该文件所在目录,这里用的是Python3,Python2应该也可以使用。

进入Python shell后如下:

Python 3.5.3 (v3.5.3:1880cb95a742, Jan 16 2017, 16:02:32) [MSC v.1900 64 bit (AMD64)] on win32
Type "help", "copyright", "credits" or "license" for more information.
>>> from frenchdeck import *
>>> deck = FrenchDeck()
>>> len(deck)
52
>>> deck[0]
Card(rank='', suit='spades')
>>> deck[-1]
Card(rank='A', suit='hearts')
>>>

通过上面的这个例子,我们可以看到,当我们在使用len(deck)和deck[0]时,Python的解释器实际上分别调用了我们在自定义类中的__len__和__getitem__这两个方法。

然后,假如我们现在要在这一副“扑克牌”中,随机的抽取出一张牌,我们要怎么做呢?自己在写一个方法吗?这在Python中是不用的,Python 已经内置了从一个序列中随机选出一个元素的函数 random.choice,我们直接把它用在这一摞纸牌实例上就好(解释器代码接上面):

>>> from random import choice
>>> choice(deck)
Card(rank='', suit='hearts')
>>> choice(deck)
Card(rank='K', suit='spades')
>>> choice(deck)
Card(rank='', suit='clubs')

通过上面的两个例子,我们已经可以体会到通过实现特殊方法来利用 Python 数据模型的两个好处:

1.作为你的类的用户,他们不必去记住标准操作的各式名称(“怎么得到元素的总数?是 .size() 还是 .length() 还是别的什么?”)。

2.可以更加方便地利用 Python 的标准库,比如 random.choice 函数,从而不用重新发明轮子。

同时,我们也能了解到,这些特殊方法的调用,通常都是隐式的,首先明确一点,特殊方法的存在是为了被 Python 解释器调用的,你自己并不需要调用它们。也就是说没有 my_object.__len__() 这种写法,而应该使用 len(my_object)。在执行 len(my_object) 的时候,如果 my_object 是一个自定义类的对象,那么 Python 会自己去调用其中由你实现的 __len__ 方法。通过内置的函数(例如 len、iter、str,等等)来使用特殊方法是最好的选择。这些内置函数不仅会调用特殊方法,通常还提供额外的好处,而且对于内置的类来说,它们的速度更快。

Python 数据模型的特殊方法还有很多,想要了解更多的关于Python数据模型和特殊方法的内容,可以参见:https://docs.python.org/3/reference/datamodel.html,是最符合规范的Python知识来源。

Python学习笔记1:数据模型和特殊方法(魔术方法)的更多相关文章

  1. Python学习笔记(三):随机生成函数方法

    本文是在Python2下总结! Python中的random模块用于生成随机数,如果想生成随机数需要先导入random的模块然后才能使用其中的方法,下面简单介绍一下常用的结果函数方法: 1·.rand ...

  2. 【python学习笔记】9.魔法方法、属性和迭代器

    [python学习笔记]9.魔法方法.属性和迭代器 魔法方法:xx, 收尾各有两个下划线的方法 __init__(self): 构造方法,创建对象时候自动执行,可以为其增加参数, 父类构造方法不会被自 ...

  3. python学习笔记整理——字典

    python学习笔记整理 数据结构--字典 无序的 {键:值} 对集合 用于查询的方法 len(d) Return the number of items in the dictionary d. 返 ...

  4. python学习笔记之module && package

    个人总结: import module,module就是文件名,导入那个python文件 import package,package就是一个文件夹,导入的文件夹下有一个__init__.py的文件, ...

  5. python学习笔记--Django入门四 管理站点--二

    接上一节  python学习笔记--Django入门四 管理站点 设置字段可选 编辑Book模块在email字段上加上blank=True,指定email字段为可选,代码如下: class Autho ...

  6. python学习笔记--Django入门0 安装dangjo

    经过这几天的折腾,经历了Django的各种报错,翻译的内容虽然不错,但是与实际的版本有差别,会出现各种奇葩的错误.现在终于找到了解决方法:查看英文原版内容:http://djangobook.com/ ...

  7. OpenCV之Python学习笔记

    OpenCV之Python学习笔记 直都在用Python+OpenCV做一些算法的原型.本来想留下发布一些文章的,可是整理一下就有点无奈了,都是写零散不成系统的小片段.现在看 到一本国外的新书< ...

  8. python学习笔记(五岁以下儿童)深深浅浅的副本复印件,文件和文件夹

    python学习笔记(五岁以下儿童) 深拷贝-浅拷贝 浅拷贝就是对引用的拷贝(仅仅拷贝父对象) 深拷贝就是对对象的资源拷贝 普通的复制,仅仅是添加了一个指向同一个地址空间的"标签" ...

  9. 【Python学习笔记之二】浅谈Python的yield用法

    在上篇[Python学习笔记之一]Python关键字及其总结中我提到了yield,本篇文章我将会重点说明yield的用法 在介绍yield前有必要先说明下Python中的迭代器(iterator)和生 ...

  10. Python学习笔记(十三)

    Python学习笔记(十三): 模块 包 if name == main 软件目录结构规范 作业-ATM+购物商城程序 1. 模块 1. 模块导入方法 import 语句 import module1 ...

随机推荐

  1. ps命令学习笔记

    最近在看linux优化大师这本书,第2章祥细讲解了分析系统用的工具,这里把一些内容整理出来,以便加深印像. 当进行系统分析时,ps命令显示有关选择的活跃进程的信息.ps命令提供当前已存在的进程列表,和 ...

  2. Java IO设计模式(装饰模式与适配器模式)

    01. 装饰模式 1. 定义 Decorator装饰器,就是动态地给一个对象添加一些额外的职责,动态扩展,和下面继承(静态扩展)的比较.因此,装饰器模式具有如下的特征: 它必须持有一个被装饰的对象(作 ...

  3. 小解系列-自关联对象.Net MVC中 json序列化循环引用问题

    自关联对象在实际开发中用的还是比较多,例如常见的树形菜单.本文是自己实际的一个小测试,可以解决循环引用对象的json序列化问题,文笔不好请多见谅,如有错误请指出,希望有更好的解决方案,一起进步. 构造 ...

  4. 访问Access日期字段

    在使用sql访问Access日期字段,应在变量前后加#,例子: s:=Format(select xueshID,name,times,qukbz,skdate,banji from dianmjil ...

  5. 包装类、数组、string类浅析及练习

    String s1 = "abc"; String s2 = "abc"; System.out.println(s1==s2); //返回true Strin ...

  6. 二维坐标点排序(JavaScript)

    今天给大家分享下最近web项目中出现的一个技术难点问题--坐标排序: 如下图所示,要求在前端页面上按顺序将下面5个模块的坐标依次保存至数据库 现在已知信息如下: 1.每个模块分别为一个div 2.每个 ...

  7. 增强for循环赋值

    增强for循环赋值 代码如下: double[] testList01 = new double[5]; java.util.Scanner sc = new java.util.Scanner(Sy ...

  8. Android5.1 - 通讯录建立群组

    [问题] 在没有账户的时候,不应该有添加联系人群组的选项. 我们要把这个选项干掉. [相关log]06-23 17:25:00.804: E/GroupEditorFragment(6030): No ...

  9. 函数响应式编程及ReactiveObjC学习笔记 (三)

    之前讲了RAC如何帮我们实现KVO / 代理 / 事件 / 通知 今天先不去分析它的核心代码, 我们先看看ReactiveObjC库里面一些特别的东西,  如果大家点开ReactiveObjC目录应该 ...

  10. (转)ORACLE中SID和SERVICE_NAME的区别

    背景:之前一直分不清plsql和程序中配置文件url之间的连接,想当然的认为service_name 和jdburl后面的实例相对应,直到出错的这一天,通过这篇博客,彻底扫除了盲点. 1 问题 1.1 ...