PythonI/O进阶学习笔记_2.魔法函数
前言:
本文一切观点和测试代码是在python3的基础上。
Content:
1.什么是魔法函数,魔法函数__getitem__在python中应用。
2.python的数据模型和数据模型这种设计对python的影响
3.python常用的魔法函数
4.从len()方法看魔法函数的特点
5.魔法函数知识小结
一 python的魔法函数
1.什么是魔法函数?
- 魔法函数是Python中定义的,以__开头,__结尾,形如__fun__()的函数,一般使用已经定义好了的即可。
 - 使用这样一些函数,可以让我们自定义的类有更加强大的特性。
 - 魔法函数一般是隐式调用的,不需要我们显示调用。(即python解释器帮我们调用实现)
 
2.如何使用魔法函数?
例:我们建立一个公司类,里面有员工列表属性。需要循环打印所有员工。
普通方法为:
class Company:
def __init__(self,employee_list):
self.employee=employee_list
user_list=['ttr1','ttrr2','ttrr3']
company=Company(user_list)
for i in company.employee:
print(i)
如果说我们用python一个内置的魔法函数的话:
user_list=['ttr1','ttrr2','ttrr3']
company=Company(user_list) class Company_Magic:
def __init__(self,employee_list):
self.employee_list=employee_list
def __getitem__(self, item):
return self.employee_list[item] company2=Company_Magic(user_list)
for i in company2:
print(i)
区别:第二种直接对对象进行了for循环,第一种对对象里面的一个属性(list)进行循环。
就是第二种Company_Magic类生成的对象,是有可以迭代这个特性的。
因为__getitem__帮我们实现了一个逻辑,每次我们实现for循环的时候,for会去找company2这个对象中的__getitem__方法(实际上是先找另外一个迭代方法),并且传入0、1、2...直到抛了异常然后结束。这是解释器帮我们实现的功能。
ps.想想看如果__getitem__这个函数不管传入什么item都不报异常会怎么样?
二 python的数据模型和数据模型这种设计模式赋予python的特性
1.什么是数据模型?
数据模型其实是对 Python 框架的描述,它规范了这门语言自身构建模块的接口,这些模块包括但不限于序列、迭代器、函数、类等。
而魔法函数就是数据模型的一个概念。java中常被叫魔术方法,python常叫数据模型。
2.数据模型对python的影响
- 魔法函数不属于定义它的那个类,只是增强了类的一些功能。
 - 实现了特定的魔法函数之后,某些操作会变得特别简单。
 - 我们可以采用实现魔法函数来灵活地设计我们需要的类。
 
这点是很重要的需要明白python的类有些特性是可以被灵活设计的,只要在编码中让它遵循了某种特定的协议(魔法函数)。
三 python常用的魔法函数
__init__:最常用。
__str__:被print函数调用;这个魔法函数必须返回为string,否则抛异常。
(我记得最开始初学python调用mongodb对象的什么方法来着,返回的数据用print出来的字符串一直没问题,但是做处理的时候一直说数据格式有误,就是因为传回来的数据对象做了__str__处理。)
__len__:可以对对象使用 len()函数。在dict、list等类型中也实现了这个方法。

在pycharm中,输入dict() ,用ctrl+B 跳到dict的定义,可以看到dict具有哪些魔法方法。或者用dir({})也可以看到。
还有很多比较重要的魔法方法例如 __setattr__() 、__getattr__()、__setitem__()、__getitem__()、__iter__() 超多简化我们编程的魔法函数。
四 用__len__看魔法函数大致做了哪些事情?
在三中我们看到,dict()的定义中的魔法函数__len__()定义的内容为空,list()也是。
实际上,我们在这里看到的相当于只是一个接口的定义而已,真正的实现是在cpython中。
有关 list 定义源码位置在 Python 目录下的 include/listobject.h 内, 代码如下:
typedef struct {
    PyObject_VAR_HEAD
    /* Vector of pointers to list elements.  list[0] is ob_item[0], etc. */
    PyObject **ob_item;
    /* ob_item contains space for 'allocated' elements.  The number
     * currently in use is ob_size.
     * Invariants:
     *     0 <= ob_size <= allocated
     *     len(list) == ob_size
     *     ob_item == NULL implies ob_size == allocated == 0
     * list.sort() temporarily sets allocated to -1 to detect mutations.
     *
     * Items must normally not be NULL, except during construction when
     * the list is not yet visible outside the function that builds it.
     */
    Py_ssize_t allocated;
} PyListObject;
其中 ob_item 是指向列表元素的指针数组, list[0] 即 ob_item[0], allocated 是列表的空间大小。在 PyObject_VAR_HEAD 中, 拥有一个 ob_size 变量。
下面是 Python 目录下的 include/object.h 中的相关代码:
#define PyObject_VAR_HEAD PyVarObject ob_base;
...
...
typedef struct {
PyObject ob_base;
Py_ssize_t ob_size; /* Number of items in variable part */
} PyVarObject;
ob_size 变量存储的就是对象的长度, 所以每次调用 _len_() 方法的时候, 返回的是一个已经存储好了的变量,
五 总结
- 魔法函数是内置的前面为__的方法
 - 魔法函数是不需要显示调用的,python语法本身会隐含调用魔法函数
 - 魔法函数和对象不存在继承关系,任何对象都可以定义魔法函数
 - 魔法函数让python的各种类型组织起来了,让对象有数据类型,比如增加一个迭代类型等
 - __str__\__repr__\__add__等等多种常用魔法函数熟知会让代码更pythonic
 - python解释器其实会经可能提高很多效率,让开发者灵活性变高
 
PythonI/O进阶学习笔记_2.魔法函数的更多相关文章
- PythonI/O进阶学习笔记_1.抽象、面向对象、class/object/type
		
前言: 是自己在学习python进阶IO学习视频的时候的理解和笔记,因为很多都是本菜鸟学习时候的自己的理解,有可能理解有误. Content: - 抽象的概念和面向对象的概念?想要大概了解python ...
 - PythonI/O进阶学习笔记_5.python的set和dict
		
前言: 我一直觉得对我来说学习知识很忌讳不系统.本篇内容与上一篇 自定义序列类是有联系的. 上一篇比较通范的了解了序列类的一些协议和特性,并且有些list的内容.这篇更加具体到set和dict这两个序 ...
 - PythonI/O进阶学习笔记_6.对象引用,可变性和垃圾回收
		
前言: 没有前言了- -......这系列是整理的以前的笔记上传的,有些我自己都忘记我当时记笔记的关联关系了. 记住以后 笔记记了就是用来复习的!!!不看不就啥用没了吗!!! content: 1.p ...
 - PythonI/O进阶学习笔记_8.python的可迭代对象和迭代器、迭代设计模式
		
content: 1.什么是迭代协议 2. 什么是迭代器(Iterator)和可迭代对象(Iterable) 3. 使用迭代器和可迭代对象 4. 创建迭代器和可迭代对象 5. 迭代器设计模式 一 ...
 - PythonI/O进阶学习笔记_3.1面向对象编程_python的多态和鸭子类型
		
前言: 与第一篇的面向对象内容不同的是,第一篇中的面向对象更多的是与类.对象结合起来的概念粗浅理解,就是在编程历史中诞生的一种思想方法. 这篇的面向对象编程,更多落实到在语言设计实现中,是如何体现面向 ...
 - PythonI/O进阶学习笔记_4.自定义序列类(序列基类继承关系/可切片对象/推导式)
		
前言: 本文代码基于python3 Content: 1.python中的序列类分类 2. python序列中abc基类继承关系 3. 由list的extend等方法来看序列类的一些特定方法 4. l ...
 - PythonI/O进阶学习笔记_3.2面向对象编程_python的继承(多继承/super/MRO/抽象基类/mixin模式)
		
前言: 本篇相关内容分为3篇多态.继承.封装,这篇为第二篇 继承. 本篇内容围绕 python基础教程这段: 在面向对象编程中,术语对象大致意味着一系列数据(属性)以及一套访问和操作这些数据的方法.使 ...
 - PythonI/O进阶学习笔记_3.2面向对象编程_python的封装
		
前言: 本篇相关内容分为3篇多态.继承.封装,这篇为第三篇 封装. 本篇内容围绕 python基础教程这段: 在面向对象编程中,术语对象大致意味着一系列数据(属性)以及一套访问和操作这些数据的方法.使 ...
 - PythonI/O进阶学习笔记_7.python动态属性,__new__和__init__和元类编程(上)
		
content: 上: 1.property动态属性 2.__getattr__和__setattr__的区别和在属性查找中的作用 3.属性描述符 和属性查找过程 4.__new__和__init__ ...
 
随机推荐
- maven打包添加依赖
			
<plugins> <plugin> <artifactId>maven-assembly-plugin</artifactId> <versio ...
 - MYSQL A、B表数组关联查询
			
最终结果: 数据库表 A表: B表: 操作步骤 主要关键字:FIND_IN_SET.GROUP_CONCAT.LEFT JOIN.GROUP BY 第一步:left join 连接AB表并通过 fin ...
 - 【MySQL】ON DUPLICATE KEY UPDATE
			
之前没用过这个操作,甚至没见过--最近接触到,而且还挺有用. 作用:若 KEY 不重复,则插入记录:否则更新记录. 单条操作: INSERT INTO table(a, b, c) VALUES (1 ...
 - 【Android】Failed to convert @drawable/picture into a drawable
			
刚使用 eclipse 遇到了这个问题,图片的效果未显示出来,上网查找后发现这其实不算是问题:重启下工程或 eclipse 就行了. PS: 直接运行工程也可以,不影响效果.
 - "A valid provisioning profile for this executable was not found"问题
			
时间:2015年8月14日 初接触iOS,这两天真机调试的时候遇到了这个问题.如图所示: 上网查后发现,解决方法大致有以下两种: 1. provisioning profile没有被找到,需要重新导入 ...
 - 安装MySQL5.7 安装环境:CentOS7 64位 MINI版,
			
安装环境:CentOS7 64位 MINI版,安装MySQL5.7 1.配置YUM源 在MySQL官网中下载YUM源rpm安装包:http://dev.mysql.com/downloads/repo ...
 - RabbitMQ与spring集成,配置完整的生产者和消费者
			
RabbitMQ与AMQP协议详解可以看看这个 http://www.cnblogs.com/frankyou/p/5283539.html 下面是rabbitMQ和spring集成的配置,我配置了二 ...
 - Unity基础之:UnityAPI的学习
			
版权声明: 本文原创发布于博客园"优梦创客"的博客空间(网址:http://www.cnblogs.com/raymondking123/)以及微信公众号"优梦创客&qu ...
 - go 学习笔记之有意思的变量和不安分的常量
			
首先希望学习 Go 语言的爱好者至少拥有其他语言的编程经验,如果是完全零基础的小白用户,本教程可能并不适合阅读或尝试阅读看看,系列笔记的目标是站在其他语言的角度学习新的语言,理解 Go 语言,进而写出 ...
 - java线程池,阿里为什么不允许使用Executors?
			
带着问题 阿里Java代码规范为什么不允许使用Executors快速创建线程池? 下面的代码输出是什么? ThreadPoolExecutor executor = new ThreadPoolExe ...